home *** CD-ROM | disk | FTP | other *** search
- /* Reload pseudo regs into hard regs for insns that require hard regs.
- Copyright (C) 1987, 1988, 1989 Free Software Foundation, Inc.
-
- This file is part of GNU CC.
-
- GNU CC is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 1, or (at your option)
- any later version.
-
- GNU CC is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNU CC; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-
- #include "config.h"
- #include "rtl.h"
- #include "insn-config.h"
- #include "flags.h"
- #include "regs.h"
- #include "hard-reg-set.h"
- #include "reload.h"
- #include "recog.h"
- #include "basic-block.h"
- #include <stdio.h>
-
- #define min(A,B) ((A) < (B) ? (A) : (B))
- #define max(A,B) ((A) > (B) ? (A) : (B))
-
- /* This file contains the reload pass of the compiler, which is
- run after register allocation has been done. It checks that
- each insn is valid (operands required to be in registers really
- are in registers of the proper class) and fixes up invalid ones
- by copying values temporarily into registers for the insns
- that need them.
-
- The results of register allocation are described by the vector
- reg_renumber; the insns still contain pseudo regs, but reg_renumber
- can be used to find which hard reg, if any, a pseudo reg is in.
-
- The technique we always use is to free up a few hard regs that are
- called ``reload regs'', and for each place where a pseudo reg
- must be in a hard reg, copy it temporarily into one of the reload regs.
-
- All the pseudos that were formerly allocated to the hard regs that
- are now in use as reload regs must be ``spilled''. This means
- that they go to other hard regs, or to stack slots if no other
- available hard regs can be found. Spilling can invalidate more
- insns, requiring additional need for reloads, so we must keep checking
- until the process stabilizes.
-
- For machines with different classes of registers, we must keep track
- of the register class needed for each reload, and make sure that
- we allocate enough reload registers of each class.
-
- The file reload.c contains the code that checks one insn for
- validity and reports the reloads that it needs. This file
- is in charge of scanning the entire rtl code, accumulating the
- reload needs, spilling, assigning reload registers to use for
- fixing up each insn, and generating the new insns to copy values
- into the reload registers. */
-
- /* During reload_as_needed, element N contains a REG rtx for the hard reg
- into which pseudo reg N has been reloaded (perhaps for a previous insn). */
- static rtx *reg_last_reload_reg;
-
- /* Elt N nonzero if reg_last_reload_reg[N] has been set in this insn
- for an output reload that stores into reg N. */
- static char *reg_has_output_reload;
-
- /* Elt N nonzero if hard reg N is a reload-register for an output reload
- in the current insn. */
- static char reg_is_output_reload[FIRST_PSEUDO_REGISTER];
-
- /* Element N is the constant value to which pseudo reg N is equivalent,
- or zero if pseudo reg N is not equivalent to a constant.
- find_reloads looks at this in order to replace pseudo reg N
- with the constant it stands for. */
- rtx *reg_equiv_constant;
-
- /* Element N is the address of stack slot to which pseudo reg N is equivalent.
- This is used when the address is not valid as a memory address
- (because its displacement is too big for the machine.) */
- rtx *reg_equiv_address;
-
- /* Element N is the memory slot to which pseudo reg N is equivalent,
- or zero if pseudo reg N is not equivalent to a memory slot. */
- rtx *reg_equiv_mem;
-
- /* Widest width in which each pseudo reg is referred to (via subreg). */
- static int *reg_max_ref_width;
-
- /* Element N is the insn that initialized reg N from its equivalent
- constant or memory slot. */
- static rtx *reg_equiv_init;
-
- /* During reload_as_needed, element N contains the last pseudo regno
- reloaded into the Nth reload register. This vector is in parallel
- with spill_regs. */
- static int reg_reloaded_contents[FIRST_PSEUDO_REGISTER];
-
- /* Number of spill-regs so far; number of valid elements of spill_regs. */
- static int n_spills;
-
- /* In parallel with spill_regs, contains REG rtx's for those regs.
- Holds the last rtx used for any given reg, or 0 if it has never
- been used for spilling yet. This rtx is reused, provided it has
- the proper mode. */
- static rtx spill_reg_rtx[FIRST_PSEUDO_REGISTER];
-
- /* In parallel with spill_regs, contains nonzero for a spill reg
- that was stored after the last time it was used.
- The precise value is the insn generated to do the store. */
- static rtx spill_reg_store[FIRST_PSEUDO_REGISTER];
-
- /* This table is the inverse mapping of spill_regs:
- indexed by hard reg number,
- it contains the position of that reg in spill_regs,
- or -1 for something that is not in spill_regs. */
- static short spill_reg_order[FIRST_PSEUDO_REGISTER];
-
- /* This table contains 1 for a register that may not be used
- for retrying global allocation, or -1 for a register that may be used.
- The registers that may not be used include all spill registers
- and the frame pointer (if we are using one). */
- static short forbidden_regs[FIRST_PSEUDO_REGISTER];
-
- /* Describes order of use of registers for reloading
- of spilled pseudo-registers. `spills' is the number of
- elements that are actually valid; new ones are added at the end. */
- static char spill_regs[FIRST_PSEUDO_REGISTER];
-
- /* Describes order of preference for putting regs into spill_regs.
- Contains the numbers of all the hard regs, in order most preferred first.
- This order is different for each function.
- It is set up by order_regs_for_reload.
- Empty elements at the end contain -1. */
- static short potential_reload_regs[FIRST_PSEUDO_REGISTER];
-
- /* 1 for a hard register that appears explicitly in the rtl
- (for example, function value registers, special registers
- used by insns, structure value pointer registers). */
- static char regs_explicitly_used[FIRST_PSEUDO_REGISTER];
-
- /* For each register, 1 if it was counted against the need for
- groups. 0 means it can count against max_nongroup instead. */
- static char counted_for_groups[FIRST_PSEUDO_REGISTER];
-
- /* For each register, 1 if it was counted against the need for
- non-groups. 0 means it can become part of a new group.
- During choose_reload_regs, 1 here means don't use this reg
- as part of a group, even if it seems to be otherwise ok. */
- static char counted_for_nongroups[FIRST_PSEUDO_REGISTER];
-
- /* Nonzero if spilling (REG n) does not require reloading it into
- a register in order to do (MEM (REG n)). */
-
- static char spill_indirect_ok;
-
- /* Nonzero if an address (plus (reg frame_pointer) (reg ...)) is valid. */
-
- char double_reg_address_ok;
-
- /* Record the stack slot for each spilled hard register. */
-
- static rtx spill_stack_slot[FIRST_PSEUDO_REGISTER];
-
- /* Width allocated so far for that stack slot. */
-
- static int spill_stack_slot_width[FIRST_PSEUDO_REGISTER];
-
- /* Indexed by basic block number, nonzero if there is any need
- for a spill register in that basic block.
- The pointer is 0 if we did stupid allocation and don't know
- the structure of basic blocks. */
-
- char *basic_block_needs;
-
- /* First uid used by insns created by reload in this function.
- Used in find_equiv_reg. */
- int reload_first_uid;
-
- /* Flag set by local-alloc or global-alloc if anything is live in
- a call-clobbered reg across calls. */
-
- int caller_save_needed;
-
- /* Set to 1 by alter_frame_pointer_addresses if it changes anything. */
-
- static int frame_pointer_address_altered;
-
- void mark_home_live ();
- static rtx scan_paradoxical_subregs ();
- static void reload_as_needed ();
- static int modes_equiv_for_class_p ();
- static rtx alter_frame_pointer_addresses ();
- static void alter_reg ();
- static int new_spill_reg();
- static int spill_hard_reg ();
- static void choose_reload_regs ();
- static void emit_reload_insns ();
- static void delete_output_reload ();
- static void forget_old_reloads_1 ();
- static void order_regs_for_reload ();
- static void eliminate_frame_pointer ();
- static rtx inc_for_reload ();
- static int constraint_accepts_reg_p ();
- static int count_occurrences ();
- static rtx gen_input_reload ();
-
- extern void remove_death ();
- extern rtx adj_offsettable_operand ();
-
- /* Main entry point for the reload pass, and only entry point
- in this file.
-
- FIRST is the first insn of the function being compiled.
-
- GLOBAL nonzero means we were called from global_alloc
- and should attempt to reallocate any pseudoregs that we
- displace from hard regs we will use for reloads.
- If GLOBAL is zero, we do not have enough information to do that,
- so any pseudo reg that is spilled must go to the stack.
-
- DUMPFILE is the global-reg debugging dump file stream, or 0.
- If it is nonzero, messages are written to it to describe
- which registers are seized as reload regs, which pseudo regs
- are spilled from them, and where the pseudo regs are reallocated to. */
-
- void
- reload (first, global, dumpfile)
- rtx first;
- int global;
- FILE *dumpfile;
- {
- register int class;
- register int i;
- register rtx insn;
-
- int something_changed;
- int something_needs_reloads;
- int new_basic_block_needs;
-
- /* The basic block number currently being processed for INSN. */
- int this_block;
-
- /* Often (MEM (REG n)) is still valid even if (REG n) is put on the stack.
- Set spill_indirect_ok if so. */
- register rtx tem
- = gen_rtx (MEM, Pmode,
- gen_rtx (PLUS, Pmode,
- gen_rtx (REG, Pmode, FRAME_POINTER_REGNUM),
- gen_rtx (CONST_INT, VOIDmode, 4)));
-
- spill_indirect_ok = memory_address_p (QImode, tem);
-
- tem = gen_rtx (PLUS, Pmode,
- gen_rtx (REG, Pmode, FRAME_POINTER_REGNUM),
- gen_rtx (REG, Pmode, FRAME_POINTER_REGNUM));
- /* This way, we make sure that reg+reg is an offsettable address. */
- tem = plus_constant (tem, 4);
-
- double_reg_address_ok = memory_address_p (QImode, tem);
-
- /* Enable find_equiv_reg to distinguish insns made by reload. */
- reload_first_uid = get_max_uid ();
-
- basic_block_needs = 0;
-
- /* Remember which hard regs appear explicitly
- before we merge into `regs_ever_live' the ones in which
- pseudo regs have been allocated. */
- bcopy (regs_ever_live, regs_explicitly_used, sizeof regs_ever_live);
-
- /* We don't have a stack slot for any spill reg yet. */
- bzero (spill_stack_slot, sizeof spill_stack_slot);
- bzero (spill_stack_slot_width, sizeof spill_stack_slot_width);
-
- /* Compute which hard registers are now in use
- as homes for pseudo registers.
- This is done here rather than (eg) in global_alloc
- because this point is reached even if not optimizing. */
-
- for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
- mark_home_live (i);
-
- /* Make sure that the last insn in the chain
- is not something that needs reloading. */
- emit_note (0, NOTE_INSN_DELETED);
-
- /* Find all the pseudo registers that didn't get hard regs
- but do have known equivalent constants or memory slots.
- These include parameters (known equivalent to parameter slots)
- and cse'd or loop-moved constant memory addresses.
-
- Record constant equivalents in reg_equiv_constant
- so they will be substituted by find_reloads.
- Record memory equivalents in reg_mem_equiv so they can
- be substituted eventually by altering the REG-rtx's. */
-
- reg_equiv_constant = (rtx *) alloca (max_regno * sizeof (rtx));
- bzero (reg_equiv_constant, max_regno * sizeof (rtx));
- reg_equiv_mem = (rtx *) alloca (max_regno * sizeof (rtx));
- bzero (reg_equiv_mem, max_regno * sizeof (rtx));
- reg_equiv_init = (rtx *) alloca (max_regno * sizeof (rtx));
- bzero (reg_equiv_init, max_regno * sizeof (rtx));
- reg_equiv_address = (rtx *) alloca (max_regno * sizeof (rtx));
- bzero (reg_equiv_address, max_regno * sizeof (rtx));
- reg_max_ref_width = (int *) alloca (max_regno * sizeof (int));
- bzero (reg_max_ref_width, max_regno * sizeof (int));
-
- /* Look for REG_EQUIV notes; record what each pseudo is equivalent to.
- Also find all paradoxical subregs
- and find largest such for each pseudo. */
-
- for (insn = first; insn; insn = NEXT_INSN (insn))
- {
- if (GET_CODE (insn) == INSN
- && GET_CODE (PATTERN (insn)) == SET
- && GET_CODE (SET_DEST (PATTERN (insn))) == REG)
- {
- rtx note = find_reg_note (insn, REG_EQUIV, 0);
- if (note)
- {
- rtx x = XEXP (note, 0);
- i = REGNO (SET_DEST (PATTERN (insn)));
- if (i >= FIRST_PSEUDO_REGISTER)
- {
- if (GET_CODE (x) == MEM)
- {
- if (memory_address_p (GET_MODE (x), XEXP (x, 0)))
- reg_equiv_mem[i] = x;
- else
- reg_equiv_address[i] = XEXP (x, 0);
- }
- else if (immediate_operand (x, VOIDmode))
- reg_equiv_constant[i] = x;
- else
- continue;
- reg_equiv_init[i] = insn;
- }
- }
- }
- if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN
- || GET_CODE (insn) == JUMP_INSN)
- scan_paradoxical_subregs (PATTERN (insn));
- }
-
- /* Does this function require a frame pointer? */
-
- frame_pointer_needed
- |= (! global || FRAME_POINTER_REQUIRED);
-
- if (! frame_pointer_needed)
- frame_pointer_needed
- = check_frame_pointer_required (reg_equiv_constant,
- reg_equiv_mem, reg_equiv_address);
-
- /* Alter each pseudo-reg rtx to contain its hard reg number.
- Delete initializations of pseudos that don't have hard regs
- and do have equivalents.
- Assign stack slots to the pseudos that lack hard regs or equivalents. */
-
- for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
- alter_reg (i, -1);
-
- #ifndef REGISTER_CONSTRAINTS
- /* If all the pseudo regs have hard regs,
- except for those that are never referenced,
- we know that no reloads are needed. */
- /* But that is not true if there are register constraints, since
- in that case some pseudos might be in the wrong kind of hard reg. */
-
- for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
- if (reg_renumber[i] == -1 && reg_n_refs[i] != 0)
- break;
-
- if (i == max_regno && frame_pointer_needed && ! caller_save_needed)
- return;
- #endif
-
- /* Compute the order of preference for hard registers to spill.
- Store them by decreasing preference in potential_reload_regs. */
-
- order_regs_for_reload ();
-
- /* So far, no hard regs have been spilled. */
- n_spills = 0;
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- {
- spill_reg_order[i] = -1;
- forbidden_regs[i] = -1;
- }
-
- if (caller_save_needed)
- frame_pointer_needed = 1;
-
- if (frame_pointer_needed)
- {
- forbidden_regs[FRAME_POINTER_REGNUM] = 1;
- spill_hard_reg (FRAME_POINTER_REGNUM, global, dumpfile);
- }
-
- if (global)
- {
- basic_block_needs = (char *)alloca (n_basic_blocks);
- bzero (basic_block_needs, n_basic_blocks);
- }
-
- /* This loop scans the entire function each go-round
- and repeats until one repetition spills no additional hard regs. */
-
- /* This flag is set when a psuedo reg is spilled,
- to require another pass. Note that getting an additional reload
- reg does not necessarily imply any pseudo reg was spilled;
- sometimes we find a reload reg that no pseudo reg was allocated in. */
- something_changed = 1;
- /* This flag is set if there are any insns that require reloading. */
- something_needs_reloads = 0;
- while (something_changed)
- {
- /* For each class, number of reload regs needed in that class.
- This is the maximum over all insns of the needs in that class
- of the individual insn. */
- int max_needs[N_REG_CLASSES];
- /* For each class, size of group of consecutive regs
- that is needed for the reloads of this class. */
- int group_size[N_REG_CLASSES];
- /* For each class, max number of consecutive groups needed.
- (Each group contains max_needs_size[CLASS] consecutive registers.) */
- int max_groups[N_REG_CLASSES];
- /* For each class, max number needed of regs that don't belong
- to any of the groups. */
- int max_nongroups[N_REG_CLASSES];
- /* For each class, the machine mode which requires consecutive
- groups of regs of that class.
- If two different modes ever require groups of one class,
- they must be the same size and equally restrictive for that class,
- otherwise we can't handle the complexity. */
- enum machine_mode group_mode[N_REG_CLASSES];
-
- something_changed = 0;
- bzero (max_needs, sizeof max_needs);
- bzero (max_groups, sizeof max_groups);
- bzero (max_nongroups, sizeof max_nongroups);
- bzero (group_size, sizeof group_size);
- for (i = 0; i < N_REG_CLASSES; i++)
- group_mode[i] = VOIDmode;
-
- /* Keep track of which basic blocks are needing the reloads. */
- this_block = 0;
-
- /* Remember whether any element of basic_block_needs
- changes from 0 to 1 in this pass. */
- new_basic_block_needs = 0;
-
- /* Compute the most additional registers needed by any instruction.
- Collect information separately for each class of regs. */
-
- for (insn = first; insn; insn = NEXT_INSN (insn))
- {
- if (global && this_block + 1 < n_basic_blocks
- && insn == basic_block_head[this_block+1])
- ++this_block;
-
- if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
- || GET_CODE (insn) == CALL_INSN)
- {
- /* Initially, count RELOAD_OTHER reloads.
- Later, merge in the other kinds. */
- int insn_needs[N_REG_CLASSES];
- int insn_groups[N_REG_CLASSES];
- int insn_total_groups = 0;
-
- /* Count RELOAD_FOR_INPUT_RELOAD_ADDRESS reloads. */
- int insn_needs_for_inputs[N_REG_CLASSES];
- int insn_groups_for_inputs[N_REG_CLASSES];
- int insn_total_groups_for_inputs = 0;
-
- /* Count RELOAD_FOR_OUTPUT_RELOAD_ADDRESS reloads. */
- int insn_needs_for_outputs[N_REG_CLASSES];
- int insn_groups_for_outputs[N_REG_CLASSES];
- int insn_total_groups_for_outputs = 0;
-
- /* Count RELOAD_FOR_OPERAND_ADDRESS reloads. */
- int insn_needs_for_operands[N_REG_CLASSES];
- int insn_groups_for_operands[N_REG_CLASSES];
- int insn_total_groups_for_operands = 0;
-
- for (i = 0; i < N_REG_CLASSES; i++)
- {
- insn_needs[i] = 0, insn_groups[i] = 0;
- insn_needs_for_inputs[i] = 0, insn_groups_for_inputs[i] = 0;
- insn_needs_for_outputs[i] = 0, insn_groups_for_outputs[i] = 0;
- insn_needs_for_operands[i] = 0, insn_groups_for_operands[i] = 0;
- }
-
- #if 0 /* This wouldn't work nowadays, since optimize_bit_field
- looks for non-strict memory addresses. */
- /* Optimization: a bit-field instruction whose field
- happens to be a byte or halfword in memory
- can be changed to a move instruction. */
-
- if (GET_CODE (PATTERN (insn)) == SET)
- {
- rtx dest = SET_DEST (PATTERN (insn));
- rtx src = SET_SRC (PATTERN (insn));
-
- if (GET_CODE (dest) == ZERO_EXTRACT
- || GET_CODE (dest) == SIGN_EXTRACT)
- optimize_bit_field (PATTERN (insn), insn, reg_equiv_mem);
- if (GET_CODE (src) == ZERO_EXTRACT
- || GET_CODE (src) == SIGN_EXTRACT)
- optimize_bit_field (PATTERN (insn), insn, reg_equiv_mem);
- }
- #endif
-
- /* Analyze the instruction. */
-
- find_reloads (insn, 0, spill_indirect_ok, global, spill_reg_order);
-
- if (n_reloads == 0)
- continue;
-
- something_needs_reloads = 1;
-
- /* Count each reload once in every class
- containing the reload's own class. */
-
- for (i = 0; i < n_reloads; i++)
- {
- register enum reg_class *p;
- int size;
- enum machine_mode mode;
- int *this_groups;
- int *this_needs;
- int *this_total_groups;
-
- /* Don't use dummy reloads in regs
- being spilled in this block. */
- if (reload_reg_rtx[i] != 0
- && (!global || basic_block_needs[this_block])
- && spill_reg_order[REGNO (reload_reg_rtx[i])] >= 0)
- reload_reg_rtx[i] = 0;
-
- /* Don't count the dummy reloads, for which one of the
- regs mentioned in the insn can be used for reloading.
- Don't count optional reloads.
- Don't count reloads that got combined with others. */
- if (reload_reg_rtx[i] != 0
- || reload_optional[i] != 0
- || (reload_out[i] == 0 && reload_in[i] == 0))
- continue;
-
- /* Decide which time-of-use to count this reload for. */
- switch (reload_when_needed[i])
- {
- case RELOAD_OTHER:
- this_needs = insn_needs;
- this_groups = insn_groups;
- this_total_groups = &insn_total_groups;
- break;
-
- case RELOAD_FOR_INPUT_RELOAD_ADDRESS:
- this_needs = insn_needs_for_inputs;
- this_groups = insn_groups_for_inputs;
- this_total_groups = &insn_total_groups_for_inputs;
- break;
-
- case RELOAD_FOR_OUTPUT_RELOAD_ADDRESS:
- this_needs = insn_needs_for_outputs;
- this_groups = insn_groups_for_outputs;
- this_total_groups = &insn_total_groups_for_outputs;
- break;
-
- case RELOAD_FOR_OPERAND_ADDRESS:
- this_needs = insn_needs_for_operands;
- this_groups = insn_groups_for_operands;
- this_total_groups = &insn_total_groups_for_operands;
- break;
- }
-
- mode = reload_inmode[i];
- if (GET_MODE_SIZE (reload_outmode[i]) > GET_MODE_SIZE (mode))
- mode = reload_outmode[i];
- size = CLASS_MAX_NREGS (reload_reg_class[i], mode);
- if (size > 1)
- {
- /* Count number of groups needed separately from
- number of individual regs needed. */
- this_groups[(int) reload_reg_class[i]]++;
- p = reg_class_superclasses[(int) reload_reg_class[i]];
- while (*p != LIM_REG_CLASSES)
- this_groups[(int) *p++]++;
- (*this_total_groups)++;
-
- /* If a group of consecutive regs are needed,
- record which machine mode needs them.
- Crash if two dissimilar machine modes both need
- groups of consecutive regs of the same class. */
-
- if (group_mode[(int) reload_reg_class[i]] != VOIDmode
- &&
- (! modes_equiv_for_class_p (group_mode[(int) reload_reg_class[i]], mode, reload_reg_class[i])
- ||
- group_size[(int) reload_reg_class[i]] != size))
- abort ();
-
- /* Record size and mode of a group of this class. */
- group_size[(int) reload_reg_class[i]] = size;
- group_mode[(int) reload_reg_class[i]] = mode;
- }
- else if (size == 1)
- {
- this_needs[(int) reload_reg_class[i]] += 1;
- p = reg_class_superclasses[(int) reload_reg_class[i]];
- while (*p != LIM_REG_CLASSES)
- this_needs[(int) *p++] += 1;
- }
- else
- abort ();
-
- if (global)
- {
- if (! basic_block_needs[this_block])
- new_basic_block_needs = 1;
- basic_block_needs[this_block] = 1;
- }
- }
-
- /* All reloads have been counted for this insn;
- now merge the various times of use.
- This sets insn_needs, etc., to the maximum total number
- of registers needed at any point in this insn. */
-
- for (i = 0; i < N_REG_CLASSES; i++)
- {
- int this_max;
- this_max = insn_needs_for_inputs[i];
- if (insn_needs_for_outputs[i] > this_max)
- this_max = insn_needs_for_outputs[i];
- if (insn_needs_for_operands[i] > this_max)
- this_max = insn_needs_for_operands[i];
- insn_needs[i] += this_max;
- this_max = insn_groups_for_inputs[i];
- if (insn_groups_for_outputs[i] > this_max)
- this_max = insn_groups_for_outputs[i];
- if (insn_groups_for_operands[i] > this_max)
- this_max = insn_groups_for_operands[i];
- insn_groups[i] += this_max;
- }
- insn_total_groups += max (insn_total_groups_for_inputs,
- max (insn_total_groups_for_outputs,
- insn_total_groups_for_operands));
-
- /* Remember for later shortcuts which insns had any reloads. */
-
- PUT_MODE (insn, n_reloads ? QImode : VOIDmode);
-
- /* For each class, collect maximum need of any insn. */
-
- for (i = 0; i < N_REG_CLASSES; i++)
- {
- if (max_needs[i] < insn_needs[i])
- max_needs[i] = insn_needs[i];
- if (max_groups[i] < insn_groups[i])
- max_groups[i] = insn_groups[i];
- if (insn_total_groups > 0)
- if (max_nongroups[i] < insn_needs[i])
- max_nongroups[i] = insn_needs[i];
- }
- }
- /* Note that there is a continue statement above. */
- }
-
- /* Now deduct from the needs for the registers already
- available (already spilled). */
-
- bzero (counted_for_groups, sizeof counted_for_groups);
- bzero (counted_for_nongroups, sizeof counted_for_nongroups);
-
- /* Find all consecutive groups of spilled registers
- and mark each group off against the need for such groups. */
-
- for (i = 0; i < N_REG_CLASSES; i++)
- if (group_size[i] > 1)
- {
- char regmask[FIRST_PSEUDO_REGISTER];
- int j;
-
- bzero (regmask, sizeof regmask);
- /* Make a mask of all the regs that are spill regs in class I. */
- for (j = 0; j < n_spills; j++)
- if (TEST_HARD_REG_BIT (reg_class_contents[i], spill_regs[j])
- && !counted_for_groups[spill_regs[j]])
- regmask[spill_regs[j]] = 1;
- /* Find each consecutive group of them. */
- for (j = 0; j < FIRST_PSEUDO_REGISTER && max_groups[i] > 0; j++)
- if (regmask[j] && j + group_size[i] <= FIRST_PSEUDO_REGISTER
- /* Next line in case group-mode for this class
- demands an even-odd pair. */
- && HARD_REGNO_MODE_OK (j, group_mode[i]))
- {
- int k;
- for (k = 1; k < group_size[i]; k++)
- if (! regmask[j + k])
- break;
- if (k == group_size[i])
- {
- /* We found a group. Mark it off against this class's
- need for groups, and against each superclass too. */
- register enum reg_class *p;
- max_groups[i]--;
- p = reg_class_superclasses[i];
- while (*p != LIM_REG_CLASSES)
- max_groups[(int) *p++]--;
- /* Don't count these registers again. */
- counted_for_groups[j] = 1;
- for (k = 1; k < group_size[i]; k++)
- counted_for_groups[j + k] = 1;
- }
- j += k;
- }
- }
-
- /* Now count all remaining spill regs against the individual need.
- Those that weren't counted_for_groups in groups can also count against
- the not-in-group need. */
-
- for (i = 0; i < n_spills; i++)
- {
- register enum reg_class *p;
- class = (int) REGNO_REG_CLASS (spill_regs[i]);
-
- max_needs[class]--;
- p = reg_class_superclasses[class];
- while (*p != LIM_REG_CLASSES)
- max_needs[(int) *p++]--;
-
- if (! counted_for_groups[spill_regs[i]])
- {
- if (max_nongroups[class] > 0)
- counted_for_nongroups[spill_regs[i]] = 1;
- max_nongroups[class]--;
- p = reg_class_superclasses[class];
- while (*p != LIM_REG_CLASSES)
- {
- if (max_nongroups[(int) *p] > 0)
- counted_for_nongroups[spill_regs[i]] = 1;
- max_nongroups[(int) *p++]--;
- }
- }
- }
-
- /* If all needs are met, we win. */
-
- for (i = 0; i < N_REG_CLASSES; i++)
- if (max_needs[i] > 0 || max_groups[i] > 0 || max_nongroups[i] > 0)
- break;
- if (i == N_REG_CLASSES && !new_basic_block_needs)
- break;
-
- /* Not all needs are met; must spill more hard regs. */
-
- /* If any element of basic_block_needs changed from 0 to 1,
- re-spill all the regs already spilled. This may spill
- additional pseudos that didn't spill before. */
-
- if (new_basic_block_needs)
- for (i = 0; i < n_spills; i++)
- something_changed
- |= spill_hard_reg (spill_regs[i], global, dumpfile);
-
- /* Now find more reload regs to satisfy the remaining need
- Do it by ascending class number, since otherwise a reg
- might be spilled for a big class and might fail to count
- for a smaller class even though it belongs to that class.
-
- Count spilled regs in `spills', and add entries to
- `spill_regs' and `spill_reg_order'. */
-
- for (class = 0; class < N_REG_CLASSES; class++)
- {
- /* First get the groups of registers.
- If we got single registers first, we might fragment
- possible groups. */
- while (max_groups[class] > 0)
- {
- /* Groups of size 2 (the only groups used on most machines)
- are treated specially. */
- if (group_size[class] == 2)
- {
- /* First, look for a register that will complete a group. */
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- {
- int j = potential_reload_regs[i];
- int other;
- if (j >= 0 && !fixed_regs[j]
- &&
- ((j > 0 && (other = j - 1, spill_reg_order[other] >= 0)
- && TEST_HARD_REG_BIT (reg_class_contents[class], j)
- && TEST_HARD_REG_BIT (reg_class_contents[class], other)
- && HARD_REGNO_MODE_OK (other, group_mode[class])
- && ! counted_for_nongroups[other]
- /* We don't want one part of another group.
- We could get "two groups" that overlap! */
- && ! counted_for_groups[other])
-
- ||
- (j < FIRST_PSEUDO_REGISTER - 1
- && (other = j + 1, spill_reg_order[other] >= 0)
- && TEST_HARD_REG_BIT (reg_class_contents[class], j)
- && TEST_HARD_REG_BIT (reg_class_contents[class], other)
- && HARD_REGNO_MODE_OK (j, group_mode[class])
- && ! counted_for_nongroups[other]
- && ! counted_for_groups[other])))
- {
- register enum reg_class *p;
-
- /* We have found one that will complete a group,
- so count off one group as provided. */
- max_groups[class]--;
- p = reg_class_superclasses[class];
- while (*p != LIM_REG_CLASSES)
- max_groups[(int) *p++]--;
-
- /* Indicate both these regs are part of a group. */
- counted_for_groups[j] = 1;
- counted_for_groups[other] = 1;
-
- break;
- }
- }
- /* We can't complete a group, so start one. */
- if (i == FIRST_PSEUDO_REGISTER)
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- {
- int j = potential_reload_regs[i];
- if (j >= 0 && j + 1 < FIRST_PSEUDO_REGISTER
- && spill_reg_order[j] < 0 && spill_reg_order[j + 1] < 0
- && TEST_HARD_REG_BIT (reg_class_contents[class], j)
- && TEST_HARD_REG_BIT (reg_class_contents[class], j + 1)
- && HARD_REGNO_MODE_OK (j, group_mode[class])
- && ! counted_for_nongroups[j + 1])
- break;
- }
-
- /* I should be the index in potential_reload_regs
- of the new reload reg we have found. */
-
- something_changed
- |= new_spill_reg (i, class, max_needs, 0,
- global, dumpfile);
- }
- else
- {
- /* For groups of more than 2 registers,
- look for a sufficient sequence of unspilled registers,
- and spill them all at once. */
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- {
- int j = potential_reload_regs[i];
- int k;
- if (j >= 0 && j + 1 < FIRST_PSEUDO_REGISTER
- && HARD_REGNO_MODE_OK (j, group_mode[class]))
- {
- /* Check each reg in the sequence. */
- for (k = 0; k < group_size[class]; k++)
- if (! (spill_reg_order[j + k] < 0
- && !fixed_regs[j + k]
- && TEST_HARD_REG_BIT (reg_class_contents[class], j + k)))
- break;
- /* We got a full sequence, so spill them all. */
- if (k == group_size[class])
- {
- register enum reg_class *p;
- for (k = 0; k < group_size[class]; k++)
- {
- int idx;
- counted_for_groups[j + k] = 1;
- for (idx = 0; idx < FIRST_PSEUDO_REGISTER; idx++)
- if (potential_reload_regs[idx] == j + k)
- break;
- something_changed
- |= new_spill_reg (idx, class, max_needs, 0,
- global, dumpfile);
- }
-
- /* We have found one that will complete a group,
- so count off one group as provided. */
- max_groups[class]--;
- p = reg_class_superclasses[class];
- while (*p != LIM_REG_CLASSES)
- max_groups[(int) *p++]--;
-
- break;
- }
- }
- }
- }
- }
-
- /* Now similarly satisfy all need for single registers. */
-
- while (max_needs[class] > 0 || max_nongroups[class] > 0)
- {
- /* Consider the potential reload regs that aren't
- yet in use as reload regs, in order of preference.
- Find the most preferred one that's in this class. */
-
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- if (potential_reload_regs[i] >= 0
- && TEST_HARD_REG_BIT (reg_class_contents[class],
- potential_reload_regs[i]))
- break;
-
- /* I should be the index in potential_reload_regs
- of the new reload reg we have found. */
-
- something_changed
- |= new_spill_reg (i, class, max_needs, max_nongroups,
- global, dumpfile);
- }
- }
- }
-
- /* Insert code to save and restore call-clobbered hard regs
- around calls. */
-
- if (caller_save_needed)
- save_call_clobbered_regs ();
-
- /* Now we know for certain whether we have a frame pointer.
- If not, correct all references to go through the stack pointer.
- This must be done before reloading, since reloading could generate
- insns where sp+const cannot validly replace the frame pointer.
- *This will lose if an insn might need more spill regs after
- frame pointer elimination than it needed before.* */
-
- if (! frame_pointer_needed)
- eliminate_frame_pointer (first);
-
- /* Use the reload registers where necessary
- by generating move instructions to move the must-be-register
- values into or out of the reload registers. */
-
- if (something_needs_reloads)
- reload_as_needed (first, global);
-
- /* Now eliminate all pseudo regs by modifying them into
- their equivalent memory references.
- The REG-rtx's for the pseudos are modified in place,
- so all insns that used to refer to them now refer to memory.
-
- For a reg that has a reg_equiv_address, all those insns
- were changed by reloading so that no insns refer to it any longer;
- but the DECL_RTL of a variable decl may refer to it,
- and if so this causes the debugging info to mention the variable. */
-
- for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
- {
- rtx addr = 0;
- if (reg_equiv_mem[i])
- addr = XEXP (reg_equiv_mem[i], 0);
- if (reg_equiv_address[i])
- addr = reg_equiv_address[i];
- if (addr)
- {
- if (! frame_pointer_needed)
- FIX_FRAME_POINTER_ADDRESS (addr, 0);
- if (reg_renumber[i] < 0)
- {
- rtx reg = regno_reg_rtx[i];
- XEXP (reg, 0) = addr;
- REG_USERVAR_P (reg) = 0;
- PUT_CODE (reg, MEM);
- }
- else if (reg_equiv_mem[i])
- XEXP (reg_equiv_mem[i], 0) = addr;
- }
- }
- }
-
- /* 1 if two machine modes MODE0 and MODE1 are equivalent
- as far as HARD_REGNO_MODE_OK is concerned
- for registers in class CLASS. */
-
- static int
- modes_equiv_for_class_p (mode0, mode1, class)
- enum machine_mode mode0, mode1;
- enum reg_class class;
- {
- register int regno;
- for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
- {
- /* If any reg in CLASS allows one mode but not the other, fail.
- Or if the two modes have different sizes in that reg, fail. */
- if (TEST_HARD_REG_BIT (reg_class_contents[(int) class], regno)
- && (HARD_REGNO_MODE_OK (regno, mode0)
- != HARD_REGNO_MODE_OK (regno, mode1))
- && (HARD_REGNO_NREGS (regno, mode0)
- != HARD_REGNO_NREGS (regno, mode1)))
- return 0;
- }
- return 1;
- }
-
- /* Add a new register to the tables of available spill-registers
- (as well as spilling all pseudos allocated to the register).
- I is the index of this register in potential_reload_regs.
- CLASS is the regclass whose need is being satisfied.
- MAX_NEEDS and MAX_NONGROUPS are the vectors of needs,
- so that this register can count off against them.
- MAX_NONGROUPS is 0 if this register is part of a group.
- GLOBAL and DUMPFILE are the same as the args that `reload' got. */
-
- static int
- new_spill_reg (i, class, max_needs, max_nongroups, global, dumpfile)
- int i;
- int class;
- int *max_needs;
- int *max_nongroups;
- int global;
- FILE *dumpfile;
- {
- register enum reg_class *p;
- int val;
- int regno = potential_reload_regs[i];
-
- if (i >= FIRST_PSEUDO_REGISTER)
- abort (); /* Caller failed to find any register. */
-
- /* Make reg REGNO an additional reload reg. */
-
- potential_reload_regs[i] = -1;
- spill_regs[n_spills] = regno;
- spill_reg_order[regno] = n_spills;
- forbidden_regs[regno] = 1;
- if (dumpfile)
- fprintf (dumpfile, "Spilling reg %d.\n", spill_regs[n_spills]);
-
- /* Clear off the needs we just satisfied. */
-
- max_needs[class]--;
- p = reg_class_superclasses[class];
- while (*p != LIM_REG_CLASSES)
- max_needs[(int) *p++]--;
-
- if (max_nongroups && max_nongroups[class] > 0)
- {
- counted_for_nongroups[regno] = 1;
- max_nongroups[class]--;
- p = reg_class_superclasses[class];
- while (*p != LIM_REG_CLASSES)
- max_nongroups[(int) *p++]--;
- }
-
- /* Spill every pseudo reg that was allocated to this reg
- or to something that overlaps this reg. */
-
- val = spill_hard_reg (spill_regs[n_spills], global, dumpfile);
-
- regs_ever_live[spill_regs[n_spills]] = 1;
- n_spills++;
-
- return val;
- }
-
- /* Scan all insns, computing the stack depth, and convert all
- frame-pointer-relative references to stack-pointer-relative references. */
-
- static void
- eliminate_frame_pointer (first)
- rtx first;
- {
- int depth = 0;
- int max_uid = get_max_uid ();
- int *label_depth = (int *) alloca ((max_uid + 1) * sizeof (int));
- int i;
- rtx insn;
-
- for (i = 0; i <= max_uid; i++)
- label_depth[i] = -1;
-
- /* In this loop, for each forward branch we record the stack
- depth of the label it jumps to. We take advantage of the fact
- that the stack depth at a label reached by a backward branch
- is always, in GCC output, equal to the stack depth of the preceding
- unconditional jump, because it was either a loop statement or
- statement label. */
-
- for (insn = first; insn; insn = NEXT_INSN (insn))
- {
- rtx pattern = PATTERN (insn);
- switch (GET_CODE (insn))
- {
- case INSN:
- frame_pointer_address_altered = 0;
- alter_frame_pointer_addresses (pattern, depth);
- /* Rerecognize insn if changed. */
- if (frame_pointer_address_altered)
- INSN_CODE (insn) = -1;
-
- /* Notice pushes and pops; update DEPTH. */
- if (GET_CODE (pattern) == SET)
- {
- #ifdef PUSH_ROUNDING
- if (push_operand (SET_DEST (pattern),
- GET_MODE (SET_DEST (pattern))))
- depth += PUSH_ROUNDING (GET_MODE_SIZE (GET_MODE (SET_DEST (pattern))));
- #endif
- if (GET_CODE (SET_DEST (pattern)) == REG
- && REGNO (SET_DEST (pattern)) == STACK_POINTER_REGNUM)
- {
- int delta;
- if (GET_CODE (SET_SRC (pattern)) == PLUS
- && GET_CODE (XEXP (SET_SRC (pattern), 0)) == REG
- && REGNO (XEXP (SET_SRC (pattern), 0)) == STACK_POINTER_REGNUM)
- delta = INTVAL (XEXP (SET_SRC (pattern), 1));
- else if (GET_CODE (SET_SRC (pattern)) == MINUS
- && GET_CODE (XEXP (SET_SRC (pattern), 0)) == REG
- && REGNO (XEXP (SET_SRC (pattern), 0)) == STACK_POINTER_REGNUM)
- delta = -INTVAL (XEXP (SET_SRC (pattern), 1));
- else abort ();
- #ifdef STACK_GROWS_DOWNWARD
- depth -= delta;
- #else
- depth += delta;
- #endif
- }
- }
- break;
-
- case JUMP_INSN:
- frame_pointer_address_altered = 0;
- alter_frame_pointer_addresses (pattern, depth);
- /* Rerecognize insn if changed. */
- if (frame_pointer_address_altered)
- INSN_CODE (insn) = -1;
-
- if (GET_CODE (pattern) == ADDR_VEC)
- for (i = 0; i < XVECLEN (pattern, 0); i++)
- label_depth[INSN_UID (XEXP (XVECEXP (pattern, 0, i), 0))] = depth;
- else if (GET_CODE (pattern) == ADDR_DIFF_VEC)
- {
- label_depth[INSN_UID (XEXP (XEXP (pattern, 0), 0))] = depth;
- for (i = 0; i < XVECLEN (pattern, 1); i++)
- label_depth[INSN_UID (XEXP (XVECEXP (pattern, 1, i), 0))] = depth;
- }
- else if (JUMP_LABEL (insn))
- label_depth[INSN_UID (JUMP_LABEL (insn))] = depth;
- else
- break;
-
- case CODE_LABEL:
- if (label_depth [INSN_UID (insn)] >= 0)
- depth = label_depth [INSN_UID (insn)];
- break;
-
- case CALL_INSN:
- frame_pointer_address_altered = 0;
- alter_frame_pointer_addresses (pattern, depth);
- /* Rerecognize insn if changed. */
- if (frame_pointer_address_altered)
- INSN_CODE (insn) = -1;
- break;
- }
- }
- }
-
- /* Walk the rtx X, converting all frame-pointer refs to stack-pointer refs
- on the assumption that the current temporary stack depth is DEPTH.
- (The size of saved registers must be added to DEPTH
- to get the actual offset between the logical frame-pointer and the
- stack pointer. FIX_FRAME_POINTER_ADDRESS takes care of that.) */
-
- static rtx
- alter_frame_pointer_addresses (x, depth)
- register rtx x;
- int depth;
- {
- register int i;
- register char *fmt;
- register enum rtx_code code = GET_CODE (x);
-
- switch (code)
- {
- case CONST_INT:
- case CONST:
- case SYMBOL_REF:
- case LABEL_REF:
- case CONST_DOUBLE:
- case CC0:
- case PC:
- return x;
-
- case REG:
- /* Frame ptr can occur outside a PLUS if a stack slot
- can occur with offset 0. */
- if (x == frame_pointer_rtx)
- {
- rtx oldx = x;
- FIX_FRAME_POINTER_ADDRESS (x, depth);
- if (x != oldx)
- frame_pointer_address_altered = 1;
- }
- return x;
-
- case MEM:
- {
- rtx addr = XEXP (x, 0);
- rtx mem;
- rtx old_addr = addr;
- FIX_FRAME_POINTER_ADDRESS (addr, depth);
- if (addr != old_addr)
- frame_pointer_address_altered = 1;
- /* These MEMs are normally shared. Make a changed copy;
- don't alter the shared MEM, since it needs to be altered
- differently each time it occurs (since DEPTH varies). */
- mem = gen_rtx (MEM, GET_MODE (x), addr);
- MEM_VOLATILE_P (mem) = MEM_VOLATILE_P (x);
- return mem;
- }
-
- case PLUS:
- {
- rtx oldx = x;
- /* Handle addresses being loaded or pushed, etc.,
- rather than referenced. */
- FIX_FRAME_POINTER_ADDRESS (x, depth);
- if (x != oldx)
- frame_pointer_address_altered = 1;
- code = GET_CODE (x);
- break;
- }
- }
-
- fmt = GET_RTX_FORMAT (code);
- for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- {
- if (fmt[i] == 'e')
- XEXP (x, i) = alter_frame_pointer_addresses (XEXP (x, i), depth);
- else if (fmt[i] == 'E')
- {
- register int j;
- for (j = XVECLEN (x, i) - 1; j >=0; j--)
- XVECEXP (x, i, j)
- = alter_frame_pointer_addresses (XVECEXP (x, i, j), depth);
- }
- }
- return x;
- }
-
- /* Modify the home of pseudo-reg I.
- The new home is present in reg_renumber[I].
-
- FROM_REG may be the hard reg that the pseudo-reg is being spilled from;
- or it may be -1, meaning there is none or it is not relevant.
- This is used so that all pseudos spilled from a given hard reg
- can share one stack slot. */
-
- static void
- alter_reg (i, from_reg)
- register int i;
- int from_reg;
- {
- /* When outputting an inline function, this can happen
- for a reg that isn't actually used. */
- if (regno_reg_rtx[i] == 0)
- return;
-
- /* If the reg got changed to a MEM at rtl-generation time,
- ignore it. */
- if (GET_CODE (regno_reg_rtx[i]) != REG)
- return;
-
- /* Modify the reg-rtx to contain the new hard reg
- number or else to contain its pseudo reg number. */
- REGNO (regno_reg_rtx[i])
- = reg_renumber[i] >= 0 ? reg_renumber[i] : i;
-
- if (reg_renumber[i] < 0 && reg_equiv_init[i])
- {
- /* Delete the insn that loads the pseudo register. */
- PUT_CODE (reg_equiv_init[i], NOTE);
- NOTE_LINE_NUMBER (reg_equiv_init[i])
- = NOTE_INSN_DELETED;
- NOTE_SOURCE_FILE (reg_equiv_init[i]) = 0;
- }
-
- /* If we have a pseudo that is needed but has no hard reg or equivalent,
- allocate a stack slot for it. */
-
- if (reg_renumber[i] < 0
- && reg_n_refs[i] > 0
- && reg_equiv_constant[i] == 0
- && reg_equiv_mem[i] == 0
- && reg_equiv_address[i] == 0)
- {
- register rtx x, addr;
- int inherent_size = PSEUDO_REGNO_BYTES (i);
- int total_size = max (inherent_size, reg_max_ref_width[i]);
-
- /* Each pseudo reg has an inherent size which comes from its own mode,
- and a total size which provides room for paradoxical subregs
- which refer to the pseudo reg in wider modes.
-
- We can use a slot already allocated if it provides both
- enough inherent space and enough total space.
- Otherwise, we allocate a new slot, making sure that it has no less
- inherent space, and no less total space, then the previous slot. */
- if (from_reg == -1)
- {
- /* No known place to spill from => no slot to reuse. */
- x = assign_stack_local (GET_MODE (regno_reg_rtx[i]), total_size);
- #ifdef BYTES_BIG_ENDIAN
- /* Cancel the big-endian correction done in assign_stack_local.
- Get the address of the beginning of the slot.
- This is so we can do a big-endian correction unconditionally
- below. */
- x = gen_rtx (MEM, GET_MODE (regno_reg_rtx[i]),
- plus_constant (XEXP (x, 0),
- inherent_size - total_size));
- #endif
- }
- /* Reuse a stack slot if possible. */
- else if (spill_stack_slot[from_reg] != 0
- && spill_stack_slot_width[from_reg] >= total_size
- && (GET_MODE_SIZE (GET_MODE (spill_stack_slot[from_reg]))
- >= inherent_size))
- x = spill_stack_slot[from_reg];
- /* Allocate a new or bigger slot. */
- else
- {
- /* Compute maximum size needed, both for inherent size
- and for total size. */
- enum machine_mode mode = GET_MODE (regno_reg_rtx[i]);
- if (spill_stack_slot[from_reg])
- {
- if (GET_MODE_SIZE (GET_MODE (spill_stack_slot[from_reg]))
- > inherent_size)
- mode = GET_MODE (spill_stack_slot[from_reg]);
- if (spill_stack_slot_width[from_reg] > total_size)
- total_size = spill_stack_slot_width[from_reg];
- }
- /* Make a slot with that size. */
- x = assign_stack_local (mode, total_size);
- #ifdef BYTES_BIG_ENDIAN
- /* Cancel the big-endian correction done in assign_stack_local.
- Get the address of the beginning of the slot.
- This is so we can do a big-endian correction unconditionally
- below. */
- x = gen_rtx (MEM, mode,
- plus_constant (XEXP (x, 0),
- GET_MODE_SIZE (mode) - total_size));
- #endif
- spill_stack_slot[from_reg] = x;
- spill_stack_slot_width[from_reg] = total_size;
- }
-
- #ifdef BYTES_BIG_ENDIAN
- /* On a big endian machine, the "address" of the slot
- is the address of the low part that fits its inherent mode. */
- if (inherent_size < total_size)
- x = gen_rtx (MEM, GET_MODE (regno_reg_rtx[i]),
- plus_constant (XEXP (x, 0),
- total_size - inherent_size));
- #endif /* BYTES_BIG_ENDIAN */
-
- addr = XEXP (x, 0);
-
- /* If the stack slot is directly addressable, substitute
- the MEM we just got directly for the old REG.
- Otherwise, record the address; we will generate hairy code
- to compute the address in a register each time it is needed. */
- if (memory_address_p (GET_MODE (regno_reg_rtx[i]), addr))
- reg_equiv_mem[i] = x;
- else
- reg_equiv_address[i] = XEXP (x, 0);
- }
- }
-
- /* Mark the slots in regs_ever_live for the hard regs
- used by pseudo-reg number REGNO. */
-
- void
- mark_home_live (regno)
- int regno;
- {
- register int i, lim;
- i = reg_renumber[regno];
- if (i < 0)
- return;
- lim = i + HARD_REGNO_NREGS (i, PSEUDO_REGNO_MODE (regno));
- while (i < lim)
- regs_ever_live[i++] = 1;
- }
-
- /* Kick all pseudos out of hard register REGNO.
- If GLOBAL is nonzero, try to find someplace else to put them.
- If DUMPFILE is nonzero, log actions taken on that file.
-
- Return nonzero if any pseudos needed to be kicked out
- or if this hard reg may appear explicitly in some instructions. */
-
- static int
- spill_hard_reg (regno, global, dumpfile)
- register int regno;
- int global;
- FILE *dumpfile;
- {
- int something_changed = 0;
- register int i;
-
- /* Spill every pseudo reg that was allocated to this reg
- or to something that overlaps this reg. */
-
- for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
- if (reg_renumber[i] >= 0
- && reg_renumber[i] <= regno
- && (reg_renumber[i]
- + HARD_REGNO_NREGS (reg_renumber[i],
- PSEUDO_REGNO_MODE (i))
- > regno))
- {
- /* If this register belongs solely to a basic block
- which needed no spilling, leave it be. */
- if (regno != FRAME_POINTER_REGNUM
- && basic_block_needs
- && reg_basic_block[i] >= 0
- && basic_block_needs[reg_basic_block[i]] == 0)
- continue;
-
- /* Mark it as no longer having a hard register home. */
- reg_renumber[i] = -1;
- /* We will need to scan everything again. */
- something_changed = 1;
- if (global)
- {
- retry_global_alloc (i, forbidden_regs);
- /* Update regs_ever_live for new home (if any). */
- mark_home_live (i);
- /* If something gets spilled to the stack,
- we must have a frame pointer, so spill the frame pointer. */
- if (reg_renumber[i] == -1 && ! frame_pointer_needed)
- {
- frame_pointer_needed = 1;
- forbidden_regs[FRAME_POINTER_REGNUM] = 1;
- spill_hard_reg (FRAME_POINTER_REGNUM, global, dumpfile);
- }
- }
- alter_reg (i, regno);
- if (dumpfile)
- {
- if (reg_renumber[i] == -1)
- fprintf (dumpfile, " Register %d now on stack.\n\n", i);
- else
- fprintf (dumpfile, " Register %d now in %d.\n\n",
- i, reg_renumber[i]);
- }
- }
-
- return something_changed || regs_explicitly_used[i];
- }
-
- /* Find all paradoxical subregs within X and update reg_max_ref_width. */
-
- static rtx
- scan_paradoxical_subregs (x)
- register rtx x;
- {
- register int i;
- register char *fmt;
- register enum rtx_code code = GET_CODE (x);
-
- switch (code)
- {
- case CONST_INT:
- case CONST:
- case SYMBOL_REF:
- case LABEL_REF:
- case CONST_DOUBLE:
- case CC0:
- case PC:
- case REG:
- case USE:
- case CLOBBER:
- return;
-
- case SUBREG:
- if (GET_CODE (SUBREG_REG (x)) == REG
- && GET_MODE_SIZE (GET_MODE (x)) > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
- reg_max_ref_width[REGNO (SUBREG_REG (x))]
- = GET_MODE_SIZE (GET_MODE (x));
- return;
- }
-
- fmt = GET_RTX_FORMAT (code);
- for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- {
- if (fmt[i] == 'e')
- scan_paradoxical_subregs (XEXP (x, i));
- else if (fmt[i] == 'E')
- {
- register int j;
- for (j = XVECLEN (x, i) - 1; j >=0; j--)
- scan_paradoxical_subregs (XVECEXP (x, i, j));
- }
- }
- }
-
- struct hard_reg_n_uses { int regno; int uses; };
-
- static int
- hard_reg_use_compare (p1, p2)
- struct hard_reg_n_uses *p1, *p2;
- {
- int tem = p1->uses - p2->uses;
- if (tem != 0) return tem;
- /* If regs are equally good, sort by regno,
- so that the results of qsort leave nothing to chance. */
- return p1->regno - p2->regno;
- }
-
- /* Choose the order to consider regs for use as reload registers
- based on how much trouble would be caused by spilling one.
- Store them in order of decreasing preference in potential_reload_regs. */
-
- static void
- order_regs_for_reload ()
- {
- register int i;
- register int o = 0;
- int large = 0;
-
- struct hard_reg_n_uses hard_reg_n_uses[FIRST_PSEUDO_REGISTER];
-
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- potential_reload_regs[i] = -1;
-
- /* Count number of uses of each hard reg by pseudo regs allocated to it
- and then order them by decreasing use. */
-
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- {
- hard_reg_n_uses[i].uses = 0;
- hard_reg_n_uses[i].regno = i;
- }
-
- for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
- {
- if (reg_renumber[i] >= 0)
- hard_reg_n_uses[reg_renumber[i]].uses += reg_n_refs[i];
- large += reg_n_refs[i];
- }
-
- /* Now fixed registers (which cannot safely be used for reloading)
- get a very high use count so they will be considered least desirable.
- Registers used explicitly in the rtl code are almost as bad. */
-
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- {
- if (fixed_regs[i])
- hard_reg_n_uses[i].uses += large + 2;
- else if (regs_explicitly_used[i])
- hard_reg_n_uses[i].uses += large + 1;
- }
- hard_reg_n_uses[FRAME_POINTER_REGNUM].uses += large + 2;
-
- qsort (hard_reg_n_uses, FIRST_PSEUDO_REGISTER,
- sizeof hard_reg_n_uses[0], hard_reg_use_compare);
-
- /* Prefer registers not so far used, for use in temporary loading.
- Among them, prefer registers not preserved by calls. */
-
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- {
- #ifdef REG_ALLOC_ORDER
- int regno = reg_alloc_order[i];
- #else
- int regno = i;
- #endif
- if (regs_ever_live[regno] == 0 && call_used_regs[regno]
- && ! fixed_regs[regno])
- potential_reload_regs[o++] = regno;
- }
-
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- {
- #ifdef REG_ALLOC_ORDER
- int regno = reg_alloc_order[i];
- #else
- int regno = i;
- #endif
- if (regs_ever_live[regno] == 0 && ! call_used_regs[regno]
- && regno != FRAME_POINTER_REGNUM)
- potential_reload_regs[o++] = regno;
- }
-
- /* Now add the regs that are already used,
- preferring those used less often. */
-
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- if (regs_ever_live[hard_reg_n_uses[i].regno] != 0)
- potential_reload_regs[o++] = hard_reg_n_uses[i].regno;
-
- #if 0
- /* For regs that are used, don't prefer those not preserved by calls
- because those are likely to contain high priority things
- that are live for short periods of time. */
-
- for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
- if (regs_ever_live[i] != 0 && ! call_used_regs[i])
- potential_reload_regs[o++] = i;
- #endif
- }
-
- /* Reload pseudo-registers into hard regs around each insn as needed.
- Additional register load insns are output before the insn that needs it
- and perhaps store insns after insns that modify the reloaded pseudo reg.
-
- reg_last_reload_reg and reg_reloaded_contents keep track of
- which pseudo-registers are already available in reload registers.
- We update these for the reloads that we perform,
- as the insns are scanned. */
-
- static void
- reload_as_needed (first, live_known)
- rtx first;
- int live_known;
- {
- register rtx insn;
- register int i;
- int this_block = 0;
- rtx x;
-
- bzero (spill_reg_rtx, sizeof spill_reg_rtx);
- reg_last_reload_reg = (rtx *) alloca (max_regno * sizeof (rtx));
- bzero (reg_last_reload_reg, max_regno * sizeof (rtx));
- reg_has_output_reload = (char *) alloca (max_regno);
- for (i = 0; i < n_spills; i++)
- reg_reloaded_contents[i] = -1;
-
- for (insn = first; insn;)
- {
- register rtx next = NEXT_INSN (insn);
-
- /* Notice when we move to a new basic block. */
- if (basic_block_needs && this_block + 1 < n_basic_blocks
- && insn == basic_block_head[this_block+1])
- ++this_block;
-
- if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
- || GET_CODE (insn) == CALL_INSN)
- {
- /* If insn has no reloads, we want these to be zero, down below. */
- bzero (reg_has_output_reload, max_regno);
- bzero (reg_is_output_reload, FIRST_PSEUDO_REGISTER);
-
- if (GET_MODE (insn) == VOIDmode)
- n_reloads = 0;
- /* First find the pseudo regs that must be reloaded for this insn.
- This info is returned in the tables reload_... (see reload.h).
- Also modify the body of INSN by substituting RELOAD
- rtx's for those pseudo regs. */
- else
- find_reloads (insn, 1, spill_indirect_ok, live_known, spill_reg_order);
-
- if (n_reloads > 0)
- {
- /* If this block has not had spilling done,
- deactivate any optional reloads lest they
- try to use a spill-reg which isn't available here.
- If we have any non-optionals that need a spill reg, abort. */
- if (basic_block_needs != 0
- && basic_block_needs[this_block] == 0)
- {
- for (i = 0; i < n_reloads; i++)
- {
- if (reload_optional[i])
- reload_in[i] = reload_out[i] = 0;
- else if (reload_reg_rtx[i] == 0)
- abort ();
- }
- }
-
- /* Now compute which reload regs to reload them into. Perhaps
- reusing reload regs from previous insns, or else output
- load insns to reload them. Maybe output store insns too.
- Record the choices of reload reg in reload_reg_rtx. */
- choose_reload_regs (insn);
-
- /* Generate the insns to reload operands into or out of
- their reload regs. */
- emit_reload_insns (insn);
-
- /* Substitute the chosen reload regs from reload_reg_rtx
- into the insn's body (or perhaps into the bodies of other
- load and store insn that we just made for reloading
- and that we moved the structure into). */
- subst_reloads ();
- }
- /* Any previously reloaded spilled pseudo reg, stored in this insn,
- is no longer validly lying around to save a future reload.
- Note that this does not detect pseudos that were reloaded
- for this insn in order to be stored in
- (obeying register constraints). That is correct; such reload
- registers ARE still valid. */
- note_stores (PATTERN (insn), forget_old_reloads_1);
-
- /* Likewise for regs altered by auto-increment in this insn.
- But note that the reg-notes are not changed by reloading:
- they still contain the pseudo-regs, not the spill regs. */
- for (x = REG_NOTES (insn); x; x = XEXP (x, 1))
- if (REG_NOTE_KIND (x) == REG_INC)
- {
- /* See if this pseudo reg was reloaded in this insn.
- If so, its last-reload info is still valid
- because it is based on this insn's reload. */
- for (i = 0; i < n_reloads; i++)
- if (reload_out[i] == XEXP (x, 0))
- break;
-
- if (i != n_reloads)
- forget_old_reloads_1 (XEXP (x, 0));
- }
- }
- /* A reload reg's contents are unknown after a label. */
- if (GET_CODE (insn) == CODE_LABEL)
- for (i = 0; i < n_spills; i++)
- reg_reloaded_contents[i] = -1;
-
- /* Don't assume a reload reg is still good after a call insn
- if it is a call-used reg. */
- if (GET_CODE (insn) == CODE_LABEL || GET_CODE (insn) == CALL_INSN)
- for (i = 0; i < n_spills; i++)
- if (call_used_regs[spill_regs[i]])
- reg_reloaded_contents[i] = -1;
-
- /* In case registers overlap, allow certain insns to invalidate
- particular hard registers. */
-
- #ifdef INSN_CLOBBERS_REGNO_P
- for (i = 0 ; i < n_spills ; i++)
- if (INSN_CLOBBERS_REGNO_P (insn, spill_regs[i]))
- reg_reloaded_contents[i] = -1;
- #endif
-
- insn = next;
-
- #ifdef USE_C_ALLOCA
- alloca (0);
- #endif
- }
- }
-
- /* Discard all record of any value reloaded from X,
- or reloaded in X from someplace else;
- unless X is an output reload reg of the current insn.
-
- X may be a hard reg (the reload reg)
- or it may be a pseudo reg that was reloaded from.
-
- This function is not called for instructions generated by reload. */
-
- static void
- forget_old_reloads_1 (x)
- rtx x;
- {
- register int regno;
- int nr;
-
- if (GET_CODE (x) != REG)
- return;
-
- regno = REGNO (x);
-
- if (regno >= FIRST_PSEUDO_REGISTER)
- nr = 1;
- else
- {
- int i;
- nr = HARD_REGNO_NREGS (regno, GET_MODE (x));
- /* Storing into a spilled-reg invalidates its contents.
- This can happen if a block-local pseudo is allocated to that reg
- and it wasn't spilled because this block's total need is 0.
- Then some insn might have an optional reload and use this reg. */
- for (i = 0; i < nr; i++)
- if (spill_reg_order[regno + i] >= 0
- /* But don't do this if the reg actually serves as an output
- reload reg in the current instruction. */
- && reg_is_output_reload[regno + i] == 0)
- reg_reloaded_contents[spill_reg_order[regno + i]] = -1;
- }
-
- /* Since value of X has changed,
- forget any value previously copied from it. */
-
- while (nr-- > 0)
- /* But don't forget a copy if this is the output reload
- that establishes the copy's validity. */
- if (reg_has_output_reload[regno + nr] == 0)
- reg_last_reload_reg[regno + nr] = 0;
- }
-
- /* Comparison function for qsort to decide which of two reloads
- should be handled first. *P1 and *P2 are the reload numbers. */
-
- static int
- reload_reg_class_lower (p1, p2)
- short *p1, *p2;
- {
- register int r1 = *p1, r2 = *p2;
- register int t;
- register enum machine_mode mode1, mode2;
-
- /* Consider required reloads before optional ones. */
- t = reload_optional[r1] - reload_optional[r2];
- if (t != 0)
- return t;
- /* Consider all multi-reg groups first.
- This is safe because `reload' fills all group-need before
- filling all non-group need. */
- mode1 = (reload_inmode[r1] == VOIDmode ? reload_outmode[r1] : reload_inmode[r1]);
- mode2 = (reload_inmode[r2] == VOIDmode ? reload_outmode[r2] : reload_inmode[r2]);
- t = (CLASS_MAX_NREGS (reload_reg_class[r2], mode2)
- - CLASS_MAX_NREGS (reload_reg_class[r1], mode1));
- if (t != 0)
- return t;
- /* Consider reloads in order of increasing reg-class number. */
- t = (int) reload_reg_class[r1] - (int) reload_reg_class[r2];
- if (t != 0) return t;
- /* If reloads are equally urgent, sort by reload number,
- so that the results of qsort leave nothing to chance. */
- return r1 - r2;
- }
-
- /* The following tables are indexed by register number,
- not by spill_regs index. */
-
- /* 1 if reg is in use as a reload reg for a RELOAD_OTHER reload. */
- static char reload_reg_in_use[FIRST_PSEUDO_REGISTER];
- /* 1 if reg is in use for a RELOAD_FOR_INPUT_RELOAD_ADDRESS reload. */
- static char reload_reg_in_use_for_inputs[FIRST_PSEUDO_REGISTER];
- /* 1 if reg is in use for a RELOAD_FOR_OUTPUT_RELOAD_ADDRESS reload. */
- static char reload_reg_in_use_for_outputs[FIRST_PSEUDO_REGISTER];
- /* 1 if reg is in use for a RELOAD_FOR_OPERAND_ADDRESS reload. */
- static char reload_reg_in_use_for_operands[FIRST_PSEUDO_REGISTER];
-
- /* 1 if reg is in use as a reload reg for any sort of reload. */
- static char reload_reg_in_use_at_all[FIRST_PSEUDO_REGISTER];
-
- /* Mark reg REGNO as in use for a reload of the sort spec'd by WHEN_NEEDED. */
-
- static void
- mark_reload_reg_in_use (regno, when_needed)
- int regno;
- enum reload_when_needed when_needed;
- {
- switch (when_needed)
- {
- case RELOAD_OTHER:
- reload_reg_in_use[regno] = 1;
- break;
-
- case RELOAD_FOR_INPUT_RELOAD_ADDRESS:
- reload_reg_in_use_for_inputs[regno] = 1;
- break;
-
- case RELOAD_FOR_OUTPUT_RELOAD_ADDRESS:
- reload_reg_in_use_for_outputs[regno] = 1;
- break;
-
- case RELOAD_FOR_OPERAND_ADDRESS:
- reload_reg_in_use_for_operands[regno] = 1;
- break;
- }
- reload_reg_in_use_at_all[regno] = 1;
- }
-
- /* 1 if reg REGNO is free as a reload reg for a reload of the sort
- specified by WHEN_NEEDED. */
-
- static int
- reload_reg_free_p (regno, when_needed)
- int regno;
- enum reload_when_needed when_needed;
- {
- /* In use for a RELOAD_OTHER means it's not available for anything. */
- if (reload_reg_in_use[regno])
- return 0;
- switch (when_needed)
- {
- case RELOAD_OTHER:
- /* In use for anything means not available for a RELOAD_OTHER. */
- return ! reload_reg_in_use_at_all[regno];
-
- /* The other three kinds of use can share a register. */
- case RELOAD_FOR_INPUT_RELOAD_ADDRESS:
- return ! reload_reg_in_use_for_inputs[regno];
- case RELOAD_FOR_OUTPUT_RELOAD_ADDRESS:
- return ! reload_reg_in_use_for_outputs[regno];
- case RELOAD_FOR_OPERAND_ADDRESS:
- return ! reload_reg_in_use_for_operands[regno];
- }
- }
-
- /* Return 1 if the value in reload reg REGNO, as used by a reload
- needed for the part of the insn specified by WHEN_NEEDED,
- is not in use for a reload in any prior part of the insn. */
-
- static int
- reload_reg_free_before_p (regno, when_needed)
- int regno;
- enum reload_when_needed when_needed;
- {
- switch (when_needed)
- {
- case RELOAD_OTHER:
- /* Since a RELOAD_OTHER reload claims the reg for the entire insn,
- its use starts from the beginning, so nothing can use it earlier. */
- return 1;
-
- /* If this use is for part of the insn,
- check the reg is not in use for any prior part. */
- case RELOAD_FOR_OUTPUT_RELOAD_ADDRESS:
- if (reload_reg_in_use_for_operands[regno])
- return 0;
- case RELOAD_FOR_OPERAND_ADDRESS:
- if (reload_reg_in_use_for_inputs[regno])
- return 0;
- case RELOAD_FOR_INPUT_RELOAD_ADDRESS:
- return 1;
- }
- }
-
- /* Return 1 if the value in reload reg REGNO, as used by a reload
- needed for the part of the insn specified by WHEN_NEEDED,
- is still available in REGNO at the end of the insn. */
-
- static int
- reload_reg_reaches_end_p (regno, when_needed)
- int regno;
- enum reload_when_needed when_needed;
- {
- switch (when_needed)
- {
- case RELOAD_OTHER:
- /* Since a RELOAD_OTHER reload claims the reg for the entire insn,
- its value must reach the end. */
- return 1;
-
- /* If this use is for part of the insn,
- its value reaches if no subsequent part uses the same register. */
- case RELOAD_FOR_INPUT_RELOAD_ADDRESS:
- if (reload_reg_in_use_for_operands[regno])
- return 0;
- case RELOAD_FOR_OPERAND_ADDRESS:
- if (reload_reg_in_use_for_outputs[regno])
- return 0;
- case RELOAD_FOR_OUTPUT_RELOAD_ADDRESS:
- return 1;
- }
- }
-
- /* Vector of reload-numbers showing the order in which the reloads should
- be processed. */
- short reload_order[MAX_RELOADS];
-
- /* Indexed by reload number, 1 if incoming value
- inherited from previous insns. */
- char reload_inherited[MAX_RELOADS];
-
- /* If non-zero, this is a place to get the value of the reload,
- rather than using reload_in. */
- rtx reload_override_in[MAX_RELOADS];
-
- /* For each reload, the index in spill_regs of the spill register used,
- or -1 if we did not need one of the spill registers for this reload. */
- int reload_spill_index[MAX_RELOADS];
-
- /* Assign hard reg targets for the pseudo-registers we must reload
- into hard regs for this insn.
- Also output the instructions to copy them in and out of the hard regs.
-
- For machines with register classes, we are responsible for
- finding a reload reg in the proper class. */
-
- static void
- choose_reload_regs (insn)
- rtx insn;
- {
- register int j;
- int have_groups = 0;
- /* Non-zero means we must reuse spill regs for multiple reloads in this insn
- or we will not have enough spill regs. */
- int must_reuse = 0;
- rtx original_reload_reg_rtx[MAX_RELOADS];
-
- /* See if we have more mandatory reloads than spill regs.
- If so, then we cannot risk optimizations that could prevent
- reloads from sharing one spill register. */
-
- {
- int tem = 0;
- for (j = 0; j < n_reloads; j++)
- if (! reload_optional[j] && reload_reg_rtx[j] == 0)
- tem++;
- if (tem > n_spills)
- must_reuse = 1;
- }
-
- bcopy (reload_reg_rtx, original_reload_reg_rtx, sizeof (reload_reg_rtx));
-
- /* If we fail to get enough regs without must_reuse,
- set must_reuse and jump back here. */
- retry:
- bzero (reload_inherited, MAX_RELOADS);
- bzero (reload_override_in, MAX_RELOADS * sizeof (rtx));
- bzero (reload_reg_in_use, FIRST_PSEUDO_REGISTER);
- bzero (reload_reg_in_use_at_all, FIRST_PSEUDO_REGISTER);
- bzero (reload_reg_in_use_for_inputs, FIRST_PSEUDO_REGISTER);
- bzero (reload_reg_in_use_for_outputs, FIRST_PSEUDO_REGISTER);
- bzero (reload_reg_in_use_for_operands, FIRST_PSEUDO_REGISTER);
-
- /* In order to be certain of getting the registers we need,
- we must sort the reloads into order of increasing register class.
- Then our grabbing of reload registers will parallel the process
- that provided the reload registers. */
-
- /* Also note whether any of the reloads wants a consecutive group of regs.
- When that happens, we must when processing the non-group reloads
- avoid (when possible) using a reload reg that would break up a group. */
-
- /* This used to look for an existing reloaded home for all
- of the reloads, and only then perform any new reloads.
- But that could lose if the reloads were done out of reg-class order
- because a later reload with a looser constraint might have an old
- home in a register needed by an earlier reload with a tighter constraint.
- It would be possible with even hairier code to detect such cases
- and handle them, but it doesn't seem worth while yet. */
-
- for (j = 0; j < n_reloads; j++)
- {
- enum machine_mode mode;
- reload_order[j] = j;
- reload_spill_index[j] = -1;
- mode = (reload_inmode[j] == VOIDmode
- || GET_MODE_SIZE (reload_outmode[j]) > GET_MODE_SIZE (reload_inmode[j])
- ? reload_outmode[j] : reload_inmode[j]);
-
- if (CLASS_MAX_NREGS (reload_reg_class[j], mode) > 1)
- have_groups = 1;
- /* If we have already decided to use a certain register,
- don't use it in another way. */
- if (reload_reg_rtx[j])
- mark_reload_reg_in_use (REGNO (reload_reg_rtx[j]), reload_when_needed[j]);
- }
-
- if (n_reloads > 1)
- qsort (reload_order, n_reloads, sizeof (short), reload_reg_class_lower);
-
- for (j = 0; j < n_reloads; j++)
- {
- register int r = reload_order[j];
- register int i;
- register rtx new;
- enum machine_mode reload_mode = reload_inmode[r];
- int h1_ok, h2_ok, h3_ok;
-
- /* Ignore reloads that got marked inoperative. */
- if (reload_out[r] == 0 && reload_in[r] == 0)
- continue;
-
- if (GET_MODE_SIZE (reload_outmode[r]) > GET_MODE_SIZE (reload_mode))
- reload_mode = reload_outmode[r];
- if (reload_strict_low[r])
- reload_mode = GET_MODE (SUBREG_REG (reload_out[r]));
-
- /* No need to find a reload-register if find_reloads chose one. */
-
- if (reload_reg_rtx[r] != 0)
- continue;
-
- /* First see if this pseudo is already available as reloaded
- for a previous insn.
- This feature is disabled for multi-register groups
- because we haven't yet any way to tell whether the entire
- value is properly preserved.
- It is also disabled when there are other reloads for mult-register
- groups, lest the inherited reload reg break up a needed group. */
-
- {
- register int regno = -1;
-
- if (reload_in[r] == 0)
- ;
- else if (GET_CODE (reload_in[r]) == REG)
- regno = REGNO (reload_in[r]);
- else if (GET_CODE (reload_in_reg[r]) == REG)
- regno = REGNO (reload_in_reg[r]);
- #if 0
- /* This won't work, since REGNO can be a pseudo reg number.
- Also, it takes much more hair to keep track of all the things
- that can invalidate an inherited reload of part of a pseudoreg. */
- else if (GET_CODE (reload_in[r]) == SUBREG
- && GET_CODE (SUBREG_REG (reload_in[r])) == REG)
- regno = REGNO (SUBREG_REG (reload_in[r])) + SUBREG_WORD (reload_in[r]);
- #endif
-
- if (regno >= 0
- && reg_last_reload_reg[regno] != 0
- && ! have_groups
- /* See comment at next use of must_reuse. */
- && ! must_reuse)
- {
- i = spill_reg_order[REGNO (reg_last_reload_reg[regno])];
-
- if (reg_reloaded_contents[i] == regno
- && HARD_REGNO_MODE_OK (spill_regs[i], reload_mode)
- && TEST_HARD_REG_BIT (reg_class_contents[(int) reload_reg_class[r]],
- spill_regs[i])
- && reload_reg_free_p (spill_regs[i], reload_when_needed[r])
- && reload_reg_free_before_p (spill_regs[i],
- reload_when_needed[r]))
- {
- /* Mark the register as in use for this part of the insn. */
- mark_reload_reg_in_use (spill_regs[i], reload_when_needed[r]);
- reload_reg_rtx[r] = reg_last_reload_reg[regno];
- reload_inherited[r] = 1;
- reload_spill_index[r] = i;
- }
- }
- }
-
- /* Here's another way to see if the value is already lying around. */
- if (reload_in[r] != 0
- && reload_reg_rtx[r] == 0
- && reload_out[r] == 0
- && (CONSTANT_P (reload_in[r])
- || GET_CODE (reload_in[r]) == PLUS
- || GET_CODE (reload_in[r]) == REG
- || GET_CODE (reload_in[r]) == MEM)
- && ! have_groups
- /* This optimization can prevent this reload from reusing
- a spill reg used for another reload. That could take away
- a spill reg that another reload will need. If we cannot
- be sure there will still be enough spill regs,
- don't do this optimization. */
- && ! must_reuse)
- {
- register rtx equiv
- = find_equiv_reg (reload_in[r], insn, reload_reg_class[r],
- -1, 0, 0, reload_mode);
- int regno;
-
- if (equiv != 0)
- regno = REGNO (equiv);
-
- /* If we found a spill reg, reject it unless it is free
- and of the desired class. */
- if (equiv != 0 && GET_CODE (equiv) == REG
- && spill_reg_order[regno] >= 0
- && reload_reg_free_before_p (regno, reload_when_needed[r]))
- {
- if (! TEST_HARD_REG_BIT (reg_class_contents[(int) reload_reg_class[r]],
- regno))
- equiv = 0;
- }
-
- if (equiv != 0 && reload_reg_in_use_at_all[regno])
- equiv = 0;
-
- if (equiv != 0 && ! HARD_REGNO_MODE_OK (regno, reload_mode))
- equiv = 0;
-
- /* We found a register that contains the value we need.
- If this register is the same as an `earlyclobber' operand
- of the current insn, just mark it as a place to reload from
- since we can't use it as the reload register itself. */
-
- if (equiv != 0)
- for (i = 0; i < n_earlyclobbers; i++)
- if (reg_overlap_mentioned_p (equiv, reload_earlyclobbers[i]))
- {
- reload_override_in[r] = equiv;
- equiv = 0;
- break;
- }
-
- /* If we found an equivalent reg, say no code need be generated
- to load it, and use it as our reload reg. */
- if (equiv != 0
- && REGNO (equiv) != FRAME_POINTER_REGNUM)
- {
- reload_reg_rtx[r] = equiv;
- reload_inherited[r] = 1;
- /* If it is a spill reg,
- mark the spill reg as in use for this insn. */
- i = spill_reg_order[REGNO (equiv)];
- if (i >= 0)
- {
- int nr = HARD_REGNO_NREGS (spill_regs[i], reload_mode);
- while (nr > 0)
- mark_reload_reg_in_use (REGNO (equiv) + --nr,
- reload_when_needed[r]);
- }
- }
- }
-
- /* If it isn't lying around, and isn't optional,
- find a place to reload it into. */
- if (reload_reg_rtx[r] != 0 || reload_optional[r] != 0)
- continue;
-
- /* Value not lying around; find a register to reload it into.
- Here I is not a regno, it is an index into spill_regs. */
- i = n_spills;
-
- #if 0
- /* The following is no longer needed now that all multi-register
- (group) reloads are processed before all solitary register reloads
- (due to changes in `reg_class_lower_p' and `reload'. */
- /* The following also fails to test HARD_REGNO_MODE_OK appropriately,
- which was hard to fix because we don't know the mode that the
- group might have that would want this register. */
-
- /* If we want just one reg, and other reloads want groups,
- first try to find a reg that can't be part of a group. */
- if (have_groups
- && CLASS_MAX_NREGS (reload_reg_class[r], reload_mode) == 1)
- for (i = 0; i < n_spills; i++)
- {
- int regno = spill_regs[i];
- int class = (int) reload_reg_class[r];
- if (reload_reg_in_use_at_all[regno] == 0
- && TEST_HARD_REG_BIT (reg_class_contents[class],
- regno)
- && !(regno + 1 < FIRST_PSEUDO_REGISTER
- && spill_reg_order[regno + 1] >= 0
- && reload_reg_in_use_at_all[regno + 1] == 0
- && TEST_HARD_REG_BIT (reg_class_contents[class],
- regno + 1))
- && !(regno > 0
- && spill_reg_order[regno - 1] >= 0
- && reload_reg_in_use_at_all[regno - 1] == 0
- && TEST_HARD_REG_BIT (reg_class_contents[class],
- regno - 1)))
- break;
- }
-
- /* If that didn't work, try to find a register that has only one
- neighbor that could make a group with it. That way, if the
- available registers are three consecutive ones, we avoid taking
- the middle one (which would leave us with no possible groups). */
-
- if (have_groups
- && CLASS_MAX_NREGS (reload_reg_class[r], reload_mode) == 1
- && i == n_spills)
- for (i = 0; i < n_spills; i++)
- {
- int regno = spill_regs[i];
- int class = (int) reload_reg_class[r];
- if (reload_reg_in_use_at_all[regno] == 0
- && TEST_HARD_REG_BIT (reg_class_contents[class],
- regno)
- && (!(regno + 1 < FIRST_PSEUDO_REGISTER
- && spill_reg_order[regno + 1] >= 0
- && reload_reg_in_use_at_all[regno + 1] == 0
- && TEST_HARD_REG_BIT (reg_class_contents[class],
- regno + 1))
- || !(regno > 0
- && spill_reg_order[regno - 1] >= 0
- && reload_reg_in_use_at_all[regno - 1] == 0
- && TEST_HARD_REG_BIT (reg_class_contents[class],
- regno - 1))))
- break;
- }
- #endif
-
- /* Now, if we want a single register and haven't yet found one,
- take any reg in the right class and not in use.
- If we want a consecutive group, here is where we look for it. */
- if (i == n_spills)
- {
- int pass;
- /* If we put this reload ahead, thinking it is a group,
- then insist on finding a group. Otherwise we can grab a
- reg that some other reload needs.
- (That can happen when we have a 68000 DATA_OR_FP_REG
- which is a group of data regs or one fp reg.)
- ??? Really it would be nicer to have smarter handling
- for that kind of reg class, where a problem like this is normal.
- Perhaps those classes should be avoided for reloading
- by use of more alternatives. */
- int force_group
- = (CLASS_MAX_NREGS (reload_reg_class[r], reload_mode) > 1);
- /* We need not be so restrictive if there are no more reloads
- for this insn. */
- if (j + 1 == n_reloads)
- force_group = 0;
-
- for (pass = 0; pass < 2; pass++)
- {
- for (i = 0; i < n_spills; i++)
- {
- int class = (int) reload_reg_class[r];
- if (reload_reg_free_p (spill_regs[i], reload_when_needed[r])
- && TEST_HARD_REG_BIT (reg_class_contents[class],
- spill_regs[i])
- /* Look first for regs to share, then for unshared. */
- && (pass || reload_reg_in_use_at_all[spill_regs[i]]))
- {
- int nr = HARD_REGNO_NREGS (spill_regs[i], reload_mode);
- /* Avoid the problem where spilling a GENERAL_OR_FP_REG
- (on 68000) got us two FP regs. If NR is 1,
- we would reject both of them. */
- if (force_group)
- nr = CLASS_MAX_NREGS (reload_reg_class[r], reload_mode);
- /* If we need only one reg, we have already won. */
- if (nr == 1)
- {
- /* But reject a single reg if we demand a group. */
- if (force_group)
- continue;
- break;
- }
- /* Otherwise check that as many consecutive regs as we need
- are available here.
- Also, don't use for a group registers that are
- needed for nongroups. */
- if (HARD_REGNO_MODE_OK (spill_regs[i], reload_mode)
- && ! counted_for_nongroups[spill_regs[i]])
- while (nr > 1)
- {
- int regno = spill_regs[i] + nr - 1;
- if (!(TEST_HARD_REG_BIT (reg_class_contents[class],
- regno)
- && spill_reg_order[regno] >= 0
- && reload_reg_free_p (regno, reload_when_needed[r])
- && ! counted_for_nongroups[regno]))
- break;
- nr--;
- }
- if (nr == 1)
- break;
- }
- }
- /* If find something on pass 1, omit pass 2. */
- if (i < n_spills)
- break;
- }
- }
-
- /* We should have found a spill register by now. */
- if (i == n_spills)
- {
- if (must_reuse)
- abort ();
- bcopy (original_reload_reg_rtx, reload_reg_rtx, sizeof (reload_reg_rtx));
- must_reuse = 1;
- goto retry;
- }
-
- /* Mark as in use for this insn the reload regs we use for this. */
- {
- int nr = HARD_REGNO_NREGS (spill_regs[i], reload_mode);
- while (nr > 0)
- {
- mark_reload_reg_in_use (spill_regs[i] + --nr,
- reload_when_needed[r]);
- reg_reloaded_contents[spill_reg_order[spill_regs[i] + nr]] = -1;
- }
- }
-
- new = spill_reg_rtx[i];
-
- if (new == 0 || GET_MODE (new) != reload_mode)
- spill_reg_rtx[i] = new = gen_rtx (REG, reload_mode, spill_regs[i]);
-
- reload_reg_rtx[r] = new;
- reload_spill_index[r] = i;
-
- /* Detect when the reload reg can't hold the reload mode.
- This used to be one `if', but Sequent compiler can't handle that. */
- if (HARD_REGNO_MODE_OK (REGNO (reload_reg_rtx[r]), reload_mode))
- if (! (reload_in[r] != 0
- && ! HARD_REGNO_MODE_OK (REGNO (reload_reg_rtx[r]),
- GET_MODE (reload_in[r]))))
- if (! (reload_out[r] != 0
- && ! HARD_REGNO_MODE_OK (REGNO (reload_reg_rtx[r]),
- GET_MODE (reload_out[r]))))
- /* The reg is OK. */
- continue;
-
- /* The reg is not OK. */
- {
- if (asm_noperands (PATTERN (insn)) < 0)
- /* It's the compiler's fault. */
- abort ();
- /* It's the user's fault; the operand's mode and constraint
- don't match. Disable this reload so we don't crash in final. */
- error_for_asm (insn,
- "`asm' operand constraint incompatible with operand size");
- reload_in[r] = 0;
- reload_out[r] = 0;
- reload_reg_rtx[r] = 0;
- reload_optional[r] = 1;
- }
- }
-
- /* If we thought we could inherit a reload, because it seemed that
- nothing else wanted the same reload register earlier in the insn,
- verify that assumption, now that all reloads have been assigned. */
-
- for (j = 0; j < n_reloads; j++)
- {
- register int r = reload_order[j];
-
- if (reload_inherited[r] && reload_reg_rtx[r] != 0
- && ! reload_reg_free_before_p (REGNO (reload_reg_rtx[r]),
- reload_when_needed[r]))
- reload_inherited[r] = 0;
-
- /* If we found a better place to reload from,
- validate it in the same fashion, if it is a reload reg. */
- if (reload_override_in[r]
- && GET_CODE (reload_override_in[r]) == REG
- && spill_reg_order[REGNO (reload_override_in[r])] >= 0
- && ! reload_reg_free_before_p (REGNO (reload_override_in[r]),
- reload_when_needed[r]))
- reload_override_in[r] = 0;
- }
-
- /* Now that reload_override_in is known valid,
- actually override reload_in. */
- for (j = 0; j < n_reloads; j++)
- if (reload_override_in[j])
- reload_in[j] = reload_override_in[j];
-
- /* For all the spill regs newly reloaded in this instruction,
- record what they were reloaded from, so subsequent instructions
- can inherit the reloads. */
-
- for (j = 0; j < n_reloads; j++)
- {
- register int r = reload_order[j];
- register int i = reload_spill_index[r];
-
- /* I is nonneg if this reload used one of the spill regs.
- If reload_reg_rtx[r] is 0, this is an optional reload
- that we opted to ignore. */
- if (i >= 0 && reload_reg_rtx[r] != 0)
- {
- /* Maybe the spill reg contains a copy of reload_out. */
- if (reload_out[r] != 0 && GET_CODE (reload_out[r]) == REG)
- {
- register int nregno = REGNO (reload_out[r]);
- reg_last_reload_reg[nregno] = reload_reg_rtx[r];
- reg_reloaded_contents[i] = nregno;
- reg_has_output_reload[nregno] = 1;
- reg_is_output_reload[spill_regs[i]] = 1;
- if (reload_when_needed[r] != RELOAD_OTHER)
- abort ();
- }
- /* Maybe the spill reg contains a copy of reload_in. */
- else if (reload_out[r] == 0
- && (GET_CODE (reload_in[r]) == REG
- || GET_CODE (reload_in_reg[r]) == REG))
- {
- register int nregno;
- if (GET_CODE (reload_in[r]) == REG)
- nregno = REGNO (reload_in[r]);
- else
- nregno = REGNO (reload_in_reg[r]);
-
- /* If there are two separate reloads (one in and one out)
- for the same (hard or pseudo) reg,
- leave reg_last_reload_reg set
- based on the output reload.
- Otherwise, set it from this input reload. */
- if (!reg_has_output_reload[nregno])
- {
- reg_last_reload_reg[nregno] = reload_reg_rtx[r];
- reg_reloaded_contents[i] = nregno;
-
- /* But don't do so if another input reload
- will clobber this one's value. */
- if (! reload_reg_reaches_end_p (spill_regs[i],
- reload_when_needed[r]))
- reg_reloaded_contents[i] = -1;
- }
- }
- /* Otherwise, the spill reg doesn't contain a copy of any reg.
- Clear out its records, lest it be taken for a copy
- of reload_in when that is no longer true. */
- else
- reg_reloaded_contents[i] = -1;
- }
-
- /* The following if-statement was #if 0'd in 1.34 (or before...).
- It's reenabled in 1.35 because supposedly nothing else
- deals with this problem. */
-
- /* If a register gets output-reloaded from a non-spill register,
- that invalidates any previous reloaded copy of it.
- But forget_old_reloads_1 won't get to see it, because
- it thinks only about the original insn. So invalidate it here. */
- if (i < 0 && reload_out[r] != 0 && GET_CODE (reload_out[r]) == REG)
- {
- register int nregno = REGNO (reload_out[r]);
- reg_last_reload_reg[nregno] = 0;
- reg_has_output_reload[nregno] = 1;
- }
- }
- }
-
- /* Output insns to reload values in and out of the chosen reload regs. */
-
- static void
- emit_reload_insns (insn)
- rtx insn;
- {
- register int j;
- rtx first_output_reload_insn = NEXT_INSN (insn);
- rtx first_other_reload_insn = insn;
- rtx first_operand_address_reload_insn = insn;
- int special;
-
- /* Now output the instructions to copy the data into and out of the
- reload registers. Do these in the order that the reloads were reported,
- since reloads of base and index registers precede reloads of operands
- and the operands may need the base and index registers reloaded. */
-
- for (j = 0; j < n_reloads; j++)
- {
- register rtx old;
- rtx store_insn;
-
- old = reload_in[j];
- if (old != 0 && ! reload_inherited[j]
- && reload_reg_rtx[j] != old
- && reload_reg_rtx[j] != 0)
- {
- register rtx reloadreg = reload_reg_rtx[j];
- rtx oldequiv = 0;
- enum machine_mode mode;
- rtx where;
- rtx this_reload_insn = 0;
-
- #if 0
- /* No longer done because these paradoxical subregs now occur
- only for regs and for spilled stack slots, and in either case
- we can safely reload in the nominal machine mode. */
-
- /* Strip off of OLD any size-increasing SUBREGs such as
- (SUBREG:SI foo:QI 0). */
-
- while (GET_CODE (old) == SUBREG && SUBREG_WORD (old) == 0
- && (GET_MODE_SIZE (GET_MODE (old))
- > GET_MODE_SIZE (GET_MODE (SUBREG_REG (old)))))
- old = SUBREG_REG (old);
- #endif
-
- /* Determine the mode to reload in.
- This is very tricky because we have three to choose from.
- There is the mode the insn operand wants (reload_inmode[J]).
- There is the mode of the reload register RELOADREG.
- There is the intrinsic mode of the operand, which we could find
- by stripping some SUBREGs.
- It turns out that RELOADREG's mode is irrelevant:
- we can change that arbitrarily.
-
- Consider (SUBREG:SI foo:QI) as an operand that must be SImode;
- then the reload reg may not support QImode moves, so use SImode.
- If foo is in memory due to spilling a pseudo reg, this is safe,
- because the QImode value is in the least significant part of a
- slot big enough for a SImode. If foo is some other sort of
- memory reference, then it is impossible to reload this case,
- so previous passes had better make sure this never happens.
-
- Then consider a one-word union which has SImode and one of its
- members is a float, being fetched as (SUBREG:SF union:SI).
- We must fetch that as SFmode because we could be loading into
- a float-only register. In this case OLD's mode is correct.
-
- Consider an immediate integer: it has VOIDmode. Here we need
- to get a mode from something else.
-
- In some cases, there is a fourth mode, the operand's
- containing mode. If the insn specifies a containing mode for
- this operand, it overrides all others.
-
- I am not sure whether the algorithm here is always right,
- but it does the right things in those cases. */
-
- mode = GET_MODE (old);
- if (mode == VOIDmode)
- mode = reload_inmode[j];
- if (reload_strict_low[j])
- mode = GET_MODE (SUBREG_REG (reload_in[j]));
-
- /* If reloading from memory, see if there is a register
- that already holds the same value. If so, reload from there.
- We can pass 0 as the reload_reg_p argument because
- any other reload has either already been emitted,
- in which case find_equiv_reg will see the reload-insn,
- or has yet to be emitted, in which case it doesn't matter
- because we will use this equiv reg right away. */
-
- if (GET_CODE (old) == MEM
- || (GET_CODE (old) == REG
- && REGNO (old) >= FIRST_PSEUDO_REGISTER
- && reg_renumber[REGNO (old)] < 0))
- oldequiv = find_equiv_reg (old, insn, GENERAL_REGS,
- -1, 0, 0, mode);
-
- /* If OLDEQUIV is a spill register, don't use it for this
- if any other reload needs it at an earlier stage of this insn
- or at this stage. */
- if (oldequiv && GET_CODE (oldequiv) == REG
- && spill_reg_order[REGNO (oldequiv)] >= 0
- && (! reload_reg_free_p (REGNO (oldequiv), reload_when_needed[j])
- || ! reload_reg_free_before_p (REGNO (oldequiv),
- reload_when_needed[j])))
- oldequiv = 0;
-
- /* If OLDEQUIV is not a spill register,
- don't use it if any other reload wants it. */
- if (oldequiv && GET_CODE (oldequiv) == REG
- && spill_reg_order[REGNO (oldequiv)] < 0)
- {
- int k;
- for (k = 0; k < n_reloads; k++)
- if (reload_reg_rtx[k] != 0 && k != j
- && reg_overlap_mentioned_p (reload_reg_rtx[k], oldequiv))
- {
- oldequiv = 0;
- break;
- }
- }
-
- if (oldequiv == 0)
- oldequiv = old;
-
- /* Encapsulate both RELOADREG and OLDEQUIV into that mode,
- then load RELOADREG from OLDEQUIV. */
-
- if (GET_MODE (reloadreg) != mode)
- reloadreg = gen_rtx (SUBREG, mode, reloadreg, 0);
- while (GET_CODE (oldequiv) == SUBREG && GET_MODE (oldequiv) != mode)
- oldequiv = SUBREG_REG (oldequiv);
- if (GET_MODE (oldequiv) != VOIDmode
- && mode != GET_MODE (oldequiv))
- oldequiv = gen_rtx (SUBREG, mode, oldequiv, 0);
-
- /* Decide where to put reload insn for this reload. */
- switch (reload_when_needed[j])
- {
- case RELOAD_OTHER:
- where = first_operand_address_reload_insn;
- break;
- case RELOAD_FOR_INPUT_RELOAD_ADDRESS:
- where = first_other_reload_insn;
- break;
- case RELOAD_FOR_OUTPUT_RELOAD_ADDRESS:
- where = first_output_reload_insn;
- break;
- case RELOAD_FOR_OPERAND_ADDRESS:
- where = insn;
- }
-
- special = 0;
-
- /* Auto-increment addresses must be reloaded in a special way. */
- if (GET_CODE (oldequiv) == POST_INC
- || GET_CODE (oldequiv) == POST_DEC
- || GET_CODE (oldequiv) == PRE_INC
- || GET_CODE (oldequiv) == PRE_DEC)
- {
- /* Prevent normal processing of this reload. */
- special = 1;
- /* Output a special code sequence for this case. */
- this_reload_insn
- = inc_for_reload (reloadreg, oldequiv, reload_inc[j], where);
- }
-
- /* If we are reloading a pseudo-register that was set by the previous
- insn, see if we can get rid of that pseudo-register entirely
- by redirecting the previous insn into our reload register. */
-
- else if (optimize && GET_CODE (old) == REG
- && REGNO (old) >= FIRST_PSEUDO_REGISTER
- && dead_or_set_p (insn, old)
- /* This is unsafe if some other reload
- uses the same reg first. */
- && (reload_when_needed[j] == RELOAD_OTHER
- || reload_when_needed[j] == RELOAD_FOR_INPUT_RELOAD_ADDRESS))
- {
- rtx temp = PREV_INSN (insn);
- while (temp && GET_CODE (temp) == NOTE)
- temp = PREV_INSN (temp);
- if (temp
- && GET_CODE (temp) == INSN
- && GET_CODE (PATTERN (temp)) == SET
- && SET_DEST (PATTERN (temp)) == old
- /* Make sure we can access insn_operand_constraint. */
- && asm_noperands (PATTERN (temp)) < 0
- /* This is unsafe if prev insn rejects our reload reg. */
- && constraint_accepts_reg_p (insn_operand_constraint[recog_memoized (temp)][0],
- reloadreg)
- /* This is unsafe if operand occurs more than once in current
- insn. Perhaps some occurrences aren't reloaded. */
- && count_occurrences (PATTERN (insn), old) == 1
- /* Don't risk splitting a matching pair of operands. */
- && ! reg_mentioned_p (old, SET_SRC (PATTERN (temp))))
- {
- /* Store into the reload register instead of the pseudo. */
- SET_DEST (PATTERN (temp)) = reloadreg;
- /* If these are the only uses of the pseudo reg,
- pretend for GDB it lives in the reload reg we used. */
- if (reg_n_deaths[REGNO (old)] == 1
- && reg_n_sets[REGNO (old)] == 1)
- {
- reg_renumber[REGNO (old)] = REGNO (reload_reg_rtx[j]);
- alter_reg (REGNO (old), -1);
- }
- special = 1;
- }
- }
-
- /* We can't do that, so output an insn to load RELOADREG.
- Keep them in the following order:
- all reloads for input reload addresses,
- all reloads for ordinary input operands,
- all reloads for addresses of non-reloaded operands,
- the insn being reloaded,
- all reloads for addresses of output reloads,
- the output reloads. */
- if (! special)
- this_reload_insn = gen_input_reload (reloadreg, oldequiv, where);
-
- /* Update where to put other reload insns. */
- if (this_reload_insn)
- switch (reload_when_needed[j])
- {
- case RELOAD_OTHER:
- if (first_other_reload_insn == first_operand_address_reload_insn)
- first_other_reload_insn = this_reload_insn;
- break;
- case RELOAD_FOR_OPERAND_ADDRESS:
- if (first_operand_address_reload_insn == insn)
- first_operand_address_reload_insn = this_reload_insn;
- if (first_other_reload_insn == insn)
- first_other_reload_insn = this_reload_insn;
- }
-
- /* reload_inc[j] was formerly processed here. */
- }
-
- /* Add a note saying the input reload reg
- dies in this insn, if anyone cares. */
- #ifdef PRESERVE_DEATH_INFO_REGNO_P
- if (old != 0
- && reload_reg_rtx[j] != old
- && reload_reg_rtx[j] != 0
- && reload_out[j] == 0
- && PRESERVE_DEATH_INFO_REGNO_P (REGNO (reload_reg_rtx[j])))
- {
- register rtx reloadreg = reload_reg_rtx[j];
-
- /* The code below is incorrect except for RELOAD_OTHER. */
- if (reload_when_needed[j] != RELOAD_OTHER)
- abort ();
-
- /* Add a death note to this insn, for an input reload. */
-
- if (! dead_or_set_p (insn, reloadreg))
- REG_NOTES (insn)
- = gen_rtx (EXPR_LIST, REG_DEAD,
- reloadreg, REG_NOTES (insn));
- }
- #endif
-
- /* ??? The following code is inadequate.
- It handles regs inherited via reg_last_reloaded_contents
- but not those inherited via find_equiv_reg.
- Note that we can't expect spill_reg_store to contain anything
- useful in the case of find_equiv_reg. */
-
- #ifdef PRESERVE_DEATH_INFO_REGNO_P
- /* For some registers it is important to keep the REG_DEATH
- notes accurate for the final pass.
- If we are inheriting an old output-reload out of such a reg,
- the reg no longer dies there, so remove the death note. */
-
- if (reload_reg_rtx[j] != 0
- && PRESERVE_DEATH_INFO_REGNO_P (REGNO (reload_reg_rtx[j]))
- && reload_inherited[j] && reload_spill_index[j] >= 0
- && GET_CODE (reload_in[j]) == REG
- && spill_reg_store[reload_spill_index[j]] != 0
- && regno_dead_p (REGNO (reload_reg_rtx[j]),
- spill_reg_store[reload_spill_index[j]]))
- {
- remove_death (REGNO (reload_reg_rtx[j]),
- spill_reg_store[reload_spill_index[j]]);
- }
- #endif
-
- /* If we are reloading a register that was recently stored in with an
- output-reload, see if we can prove there was
- actually no need to store the old value in it. */
-
- if (optimize && reload_inherited[j] && reload_spill_index[j] >= 0
- /* This is unsafe if some other reload uses the same reg first. */
- && (reload_when_needed[j] == RELOAD_OTHER
- || reload_when_needed[j] == RELOAD_FOR_INPUT_RELOAD_ADDRESS)
- && GET_CODE (reload_in[j]) == REG
- && REGNO (reload_in[j]) >= FIRST_PSEUDO_REGISTER
- && spill_reg_store[reload_spill_index[j]] != 0
- && dead_or_set_p (insn, reload_in[j])
- /* This is unsafe if operand occurs more than once in current
- insn. Perhaps some occurrences weren't reloaded. */
- && count_occurrences (PATTERN (insn), reload_in[j]) == 1)
- delete_output_reload (insn, j, reload_spill_index[j]);
-
- /* Input-reloading is done. Now do output-reloading,
- storing the value from the reload-register after the main insn
- if reload_out[j] is nonzero. */
- old = reload_out[j];
- if (old != 0
- && reload_reg_rtx[j] != old
- && reload_reg_rtx[j] != 0
- /* An output operand that dies right away
- does need a reload reg, but need not
- be copied from it. */
- && ! (GET_CODE (old) == REG
- && find_reg_note (insn, REG_DEAD, old)))
- {
- register rtx reloadreg = reload_reg_rtx[j];
- enum machine_mode mode;
-
- #if 0
- /* Strip off of OLD any size-increasing SUBREGs such as
- (SUBREG:SI foo:QI 0). */
-
- while (GET_CODE (old) == SUBREG && SUBREG_WORD (old) == 0
- && (GET_MODE_SIZE (GET_MODE (old))
- > GET_MODE_SIZE (GET_MODE (SUBREG_REG (old)))))
- old = SUBREG_REG (old);
- #endif
-
- /* Determine the mode to reload in.
- See comments above (for input reloading). */
-
- mode = GET_MODE (old);
- if (mode == VOIDmode)
- abort (); /* Should never happen for an output. */
- #if 0
- mode = reload_inmode[j];
- #endif
- if (reload_strict_low[j])
- mode = GET_MODE (SUBREG_REG (reload_out[j]));
-
- /* Encapsulate both RELOADREG and OLD into that mode,
- then load RELOADREG from OLD. */
- if (GET_MODE (reloadreg) != mode)
- reloadreg = gen_rtx (SUBREG, mode, reloadreg, 0);
- /* If OLD is a subreg, then strip it, since the subreg will
- be altered by this very reload (if it's a strict_low_part). */
- while (GET_CODE (old) == SUBREG && GET_MODE (old) != mode)
- old = SUBREG_REG (old);
- if (GET_MODE (old) != VOIDmode
- && mode != GET_MODE (old))
- old = gen_rtx (SUBREG, mode, old, 0);
- /* Output the reload insn. */
- store_insn = emit_insn_before (gen_move_insn (old, reloadreg),
- first_output_reload_insn);
- first_output_reload_insn = store_insn;
- /* If this output reload doesn't come from a spill reg,
- clear any memory of reloaded copies of the pseudo reg.
- If this output reload comes from a spill reg,
- reg_has_output_reload will make this do nothing. */
- note_stores (PATTERN (store_insn), forget_old_reloads_1);
-
- #ifdef PRESERVE_DEATH_INFO_REGNO_P
- /* If final will look at death notes for this reg,
- put one on the output-reload insn. */
- if (PRESERVE_DEATH_INFO_REGNO_P (REGNO (reloadreg)))
- REG_NOTES (store_insn)
- = gen_rtx (EXPR_LIST, REG_DEAD,
- reloadreg, REG_NOTES (store_insn));
-
- /* Move all death-notes from the insn being reloaded
- to the output reload, if they are for things used
- as inputs in this output reload. */
- if (GET_CODE (old) != REG)
- {
- /* The note we will examine next. */
- rtx reg_notes = REG_NOTES (insn);
- /* The place that pointed to this note. */
- rtx *prev_reg_note = ®_NOTES (insn);
-
- while (reg_notes)
- {
- rtx next_reg_notes = XEXP (reg_notes, 1);
- if (REG_NOTE_KIND (reg_notes) == REG_DEAD
- && reg_mentioned_p (XEXP (reg_notes, 0), old))
- {
- *prev_reg_note = next_reg_notes;
- XEXP (reg_notes, 1) = REG_NOTES (store_insn);
- REG_NOTES (store_insn) = reg_notes;
- }
- else
- prev_reg_note = &XEXP (reg_notes, 1);
-
- reg_notes = next_reg_notes;
- }
- }
- #endif
- }
- else store_insn = 0;
-
- if (reload_spill_index[j] >= 0)
- spill_reg_store[reload_spill_index[j]] = store_insn;
- }
-
- /* Move death notes from INSN to output-operand-address reload insns. */
- #ifdef PRESERVE_DEATH_INFO_REGNO_P
- {
- rtx insn1;
- /* Loop over those insns, last ones first. */
- for (insn1 = PREV_INSN (first_output_reload_insn); insn1 != insn;
- insn1 = PREV_INSN (insn1))
- if (GET_CODE (insn1) == INSN && GET_CODE (PATTERN (insn1)) == SET)
- {
- rtx source = SET_SRC (PATTERN (insn1));
-
- /* The note we will examine next. */
- rtx reg_notes = REG_NOTES (insn);
- /* The place that pointed to this note. */
- rtx *prev_reg_note = ®_NOTES (insn);
-
- /* If the note is for something used in the source of this
- output address reload insn, move the note. */
- while (reg_notes)
- {
- rtx next_reg_notes = XEXP (reg_notes, 1);
- if (REG_NOTE_KIND (reg_notes) == REG_DEAD
- && reg_mentioned_p (XEXP (reg_notes, 0), source))
- {
- *prev_reg_note = next_reg_notes;
- XEXP (reg_notes, 1) = REG_NOTES (insn1);
- REG_NOTES (insn1) = reg_notes;
- }
- else
- prev_reg_note = &XEXP (reg_notes, 1);
-
- reg_notes = next_reg_notes;
- }
- }
- }
- #endif
- }
-
- /* Emit code before BEFORE_INSN to perform an input reload of IN to RELOADREG.
- Handle case of reloading a PLUS expression (currently only happens for
- stack slots with out-of-range offset).
-
- Returns last insn emitted. */
-
- static rtx
- gen_input_reload (reloadreg, in, before_insn)
- rtx reloadreg;
- rtx in;
- rtx before_insn;
- {
- #if 0 /* Install this in version 1.37. Avoid risk for now. */
- if (GET_CODE (in) == PLUS)
- {
- /* Don't use gen_move_insn to make what is actually an add insn. */
- emit_insn_before (gen_move_insn (reloadreg, XEXP (in, 0)), before_insn);
- emit_insn_before (gen_add2_insn (reloadreg, XEXP (in, 1)), before_insn);
- }
- else
- #endif
- emit_insn_before (gen_move_insn (reloadreg, in), before_insn);
-
- return PREV_INSN (before_insn);
- }
-
- /* Delete a previously made output-reload
- whose result we now believe is not needed.
- First we double-check.
-
- INSN is the insn now being processed.
- J is the reload-number for this insn,
- and SPILL_INDEX is the index in spill_regs of the reload-reg
- being used for the reload. */
-
- static void
- delete_output_reload (insn, j, spill_index)
- rtx insn;
- int j;
- int spill_index;
- {
- register rtx i1;
-
- /* Get the raw pseudo-register referred to. */
-
- rtx reg = reload_in[j];
- while (GET_CODE (reg) == SUBREG)
- reg = SUBREG_REG (reg);
-
- /* If the pseudo-reg we are reloading is no longer referenced
- anywhere between the store into it and here,
- and no jumps or labels intervene, then the value can get
- here through the reload reg alone.
- Otherwise, give up--return. */
- for (i1 = NEXT_INSN (spill_reg_store[spill_index]);
- i1 != insn; i1 = NEXT_INSN (i1))
- {
- if (GET_CODE (i1) == CODE_LABEL || GET_CODE (i1) == JUMP_INSN)
- return;
- if ((GET_CODE (i1) == INSN || GET_CODE (i1) == CALL_INSN)
- && reg_mentioned_p (reg, PATTERN (i1)))
- return;
- }
-
- /* If this insn will store in the pseudo again,
- the previous store can be removed. */
- if (reload_out[j] == reload_in[j])
- delete_insn (spill_reg_store[spill_index]);
-
- /* See if the pseudo reg has been completely replaced
- with reload regs. If so, delete the store insn
- and forget we had a stack slot for the pseudo. */
- else if (reg_n_deaths[REGNO (reg)] == 1
- && reg_basic_block[REGNO (reg)] >= 0
- && find_regno_note (insn, REG_DEAD, REGNO (reg)))
- {
- rtx i2;
-
- /* We know that it was used only between here
- and the beginning of the current basic block.
- (We also know that the last use before INSN was
- the output reload we are thinking of deleting, but never mind that.)
- Search that range; see if any ref remains. */
- for (i2 = PREV_INSN (insn); i2; i2 = PREV_INSN (i2))
- {
- /* Uses which just store in the pseudo don't count,
- since if they are the only uses, they are dead. */
- if (GET_CODE (i2) == INSN
- && GET_CODE (PATTERN (i2)) == SET
- && SET_DEST (PATTERN (i2)) == reg)
- continue;
- if (GET_CODE (i2) == CODE_LABEL
- || GET_CODE (i2) == JUMP_INSN)
- break;
- if ((GET_CODE (i2) == INSN || GET_CODE (i2) == CALL_INSN)
- && reg_mentioned_p (reg, PATTERN (i2)))
- /* Some other ref remains;
- we can't do anything. */
- return;
- }
-
- /* Delete the now-dead stores into this pseudo. */
- for (i2 = PREV_INSN (insn); i2; i2 = PREV_INSN (i2))
- {
- /* Uses which just store in the pseudo don't count,
- since if they are the only uses, they are dead. */
- if (GET_CODE (i2) == INSN
- && GET_CODE (PATTERN (i2)) == SET
- && SET_DEST (PATTERN (i2)) == reg)
- delete_insn (i2);
- if (GET_CODE (i2) == CODE_LABEL
- || GET_CODE (i2) == JUMP_INSN)
- break;
- }
-
- /* For the debugging info,
- say the pseudo lives in this reload reg. */
- reg_renumber[REGNO (reg)] = REGNO (reload_reg_rtx[j]);
- alter_reg (REGNO (reg), -1);
- }
- }
-
-
- /* Output reload-insns to reload VALUE into RELOADREG.
- VALUE is a autoincrement or autodecrement RTX whose operand
- is a register or memory location;
- so reloading involves incrementing that location.
-
- INC_AMOUNT is the number to increment or decrement by (always positive).
- This cannot be deduced from VALUE.
-
- INSN is the insn before which the new insns should be emitted.
-
- The return value is the first of the insns emitted. */
-
- static rtx
- inc_for_reload (reloadreg, value, inc_amount, insn)
- rtx reloadreg;
- rtx value;
- int inc_amount;
- rtx insn;
- {
- /* REG or MEM to be copied and incremented. */
- rtx incloc = XEXP (value, 0);
- /* Nonzero if increment after copying. */
- int post = (GET_CODE (value) == POST_DEC || GET_CODE (value) == POST_INC);
-
- /* No hard register is equivalent to this register after
- inc/dec operation. If REG_LAST_RELOAD_REG were non-zero,
- we could inc/dec that register as well (maybe even using it for
- the source), but I'm not sure it's worth worrying about. */
- if (GET_CODE (incloc) == REG)
- reg_last_reload_reg[REGNO (incloc)] = 0;
-
- if (GET_CODE (value) == PRE_DEC || GET_CODE (value) == POST_DEC)
- inc_amount = - inc_amount;
-
- /* First handle preincrement, which is simpler. */
- if (! post)
- {
- /* If incrementing a register, assume we can
- output an insn to increment it directly. */
- if (GET_CODE (incloc) == REG &&
- (REGNO (incloc) < FIRST_PSEUDO_REGISTER
- || reg_renumber[REGNO (incloc)] >= 0))
- {
- rtx first_new
- = emit_insn_before (gen_add2_insn (incloc,
- gen_rtx (CONST_INT, VOIDmode,
- inc_amount)),
- insn);
- emit_insn_before (gen_move_insn (reloadreg, incloc), insn);
- return first_new;
- }
- else
- /* Else we must not assume we can increment the location directly
- (even though on many target machines we can);
- copy it to the reload register, increment there, then save back. */
- {
- rtx first_new
- = emit_insn_before (gen_move_insn (reloadreg, incloc), insn);
- emit_insn_before (gen_add2_insn (reloadreg,
- gen_rtx (CONST_INT, VOIDmode,
- inc_amount)),
- insn);
- emit_insn_before (gen_move_insn (incloc, reloadreg), insn);
- return first_new;
- }
- }
- /* Postincrement.
- Because this might be a jump insn or a compare, and because RELOADREG
- may not be available after the insn in an input reload,
- we must do the incrementation before the insn being reloaded for. */
- else
- {
- /* Copy the value, then increment it. */
- rtx first_new
- = emit_insn_before (gen_move_insn (reloadreg, incloc), insn);
-
- /* If incrementing a register, assume we can
- output an insn to increment it directly. */
- if (GET_CODE (incloc) == REG &&
- (REGNO (incloc) < FIRST_PSEUDO_REGISTER
- || reg_renumber[REGNO (incloc)] >= 0))
- {
- emit_insn_before (gen_add2_insn (incloc,
- gen_rtx (CONST_INT, VOIDmode,
- inc_amount)),
- insn);
- }
- else
- /* Else we must not assume we can increment INCLOC
- (even though on many target machines we can);
- increment the copy in the reload register,
- save that back, then decrement the reload register
- so it has the original value. */
- {
- emit_insn_before (gen_add2_insn (reloadreg,
- gen_rtx (CONST_INT, VOIDmode,
- inc_amount)),
- insn);
- emit_insn_before (gen_move_insn (incloc, reloadreg), insn);
- emit_insn_before (gen_sub2_insn (reloadreg,
- gen_rtx (CONST_INT, VOIDmode,
- inc_amount)),
- insn);
- }
- return first_new;
- }
- }
-
- /* Return 1 if we are certain that the constraint-string STRING allows
- the hard register REG. Return 0 if we can't be sure of this. */
-
- static int
- constraint_accepts_reg_p (string, reg)
- char *string;
- rtx reg;
- {
- int value = 0;
- int regno = true_regnum (reg);
-
- /* We win if this register is a general register
- and each alternative accepts all general registers. */
- if (! TEST_HARD_REG_BIT (reg_class_contents[(int) GENERAL_REGS], regno))
- return 0;
-
- /* Initialize for first alternative. */
- value = 0;
- /* Check that each alternative contains `g' or `r'. */
- while (1)
- switch (*string++)
- {
- case 0:
- /* If an alternative lacks `g' or `r', we lose. */
- return value;
- case ',':
- /* If an alternative lacks `g' or `r', we lose. */
- if (value == 0)
- return 0;
- /* Initialize for next alternative. */
- value = 0;
- break;
- case 'g':
- case 'r':
- value = 1;
- }
- }
-
- /* Return the number of places FIND appears within X. */
-
- static int
- count_occurrences (x, find)
- register rtx x, find;
- {
- register int i, j;
- register enum rtx_code code;
- register char *format_ptr;
- int count;
-
- if (x == find)
- return 1;
- if (x == 0)
- return 0;
-
- code = GET_CODE (x);
-
- switch (code)
- {
- case REG:
- case QUEUED:
- case CONST_INT:
- case CONST_DOUBLE:
- case SYMBOL_REF:
- case CODE_LABEL:
- case PC:
- case CC0:
- return 0;
- }
-
- format_ptr = GET_RTX_FORMAT (code);
- count = 0;
-
- for (i = 0; i < GET_RTX_LENGTH (code); i++)
- {
- switch (*format_ptr++)
- {
- case 'e':
- count += count_occurrences (XEXP (x, i), find);
- break;
-
- case 'E':
- if (XVEC (x, i) != NULL)
- {
- for (j = 0; j < XVECLEN (x, i); j++)
- count += count_occurrences (XVECEXP (x, i, j), find);
- }
- break;
- }
- }
- return count;
- }
-